Conflicts:
	src/libcoretest/lib.rs
This commit is contained in:
Marcin Fatyga 2016-11-01 15:26:22 +01:00
commit 655effedf2
1501 changed files with 41721 additions and 34051 deletions

765
src/Cargo.lock generated Normal file
View file

@ -0,0 +1,765 @@
[root]
name = "unwind"
version = "0.0.0"
dependencies = [
"core 0.0.0",
"libc 0.0.0",
]
[[package]]
name = "alloc"
version = "0.0.0"
dependencies = [
"core 0.0.0",
]
[[package]]
name = "alloc_jemalloc"
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
"core 0.0.0",
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.0.0",
]
[[package]]
name = "alloc_system"
version = "0.0.0"
dependencies = [
"core 0.0.0",
"libc 0.0.0",
]
[[package]]
name = "arena"
version = "0.0.0"
[[package]]
name = "bootstrap"
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
"cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.38 (git+https://github.com/alexcrichton/gcc-rs)",
"getopts 0.2.14 (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.17 (registry+https://github.com/rust-lang/crates.io-index)",
"md5 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "build_helper"
version = "0.1.0"
[[package]]
name = "cargotest"
version = "0.1.0"
[[package]]
name = "cmake"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "collections"
version = "0.0.0"
dependencies = [
"alloc 0.0.0",
"core 0.0.0",
"rustc_unicode 0.0.0",
]
[[package]]
name = "compiler_builtins"
version = "0.0.0"
dependencies = [
"core 0.0.0",
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "compiletest"
version = "0.0.0"
dependencies = [
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serialize 0.0.0",
]
[[package]]
name = "core"
version = "0.0.0"
[[package]]
name = "env_logger"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "error_index_generator"
version = "0.0.0"
[[package]]
name = "filetime"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "flate"
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fmt_macros"
version = "0.0.0"
[[package]]
name = "gcc"
version = "0.3.38"
source = "git+https://github.com/alexcrichton/gcc-rs#be620ac6d3ddb498cd0c700d5312c6a4c3c19597"
[[package]]
name = "gcc"
version = "0.3.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "getopts"
version = "0.0.0"
[[package]]
name = "getopts"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "graphviz"
version = "0.0.0"
[[package]]
name = "idna"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
version = "0.0.0"
dependencies = [
"core 0.0.0",
]
[[package]]
name = "libc"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "linkchecker"
version = "0.1.0"
dependencies = [
"url 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.0.0"
[[package]]
name = "log"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "matches"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "md5"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num_cpus"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "panic_abort"
version = "0.0.0"
dependencies = [
"core 0.0.0",
"libc 0.0.0",
]
[[package]]
name = "panic_unwind"
version = "0.0.0"
dependencies = [
"alloc 0.0.0",
"core 0.0.0",
"libc 0.0.0",
"unwind 0.0.0",
]
[[package]]
name = "proc_macro"
version = "0.0.0"
dependencies = [
"syntax 0.0.0",
]
[[package]]
name = "proc_macro_plugin"
version = "0.0.0"
dependencies = [
"log 0.0.0",
"proc_macro_tokens 0.0.0",
"rustc_plugin 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "proc_macro_tokens"
version = "0.0.0"
dependencies = [
"log 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rand"
version = "0.0.0"
dependencies = [
"core 0.0.0",
]
[[package]]
name = "rustbook"
version = "0.0.0"
[[package]]
name = "rustc"
version = "0.0.0"
dependencies = [
"arena 0.0.0",
"flate 0.0.0",
"fmt_macros 0.0.0",
"graphviz 0.0.0",
"log 0.0.0",
"rustc_back 0.0.0",
"rustc_bitflags 0.0.0",
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"rustc_llvm 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc-main"
version = "0.0.0"
dependencies = [
"rustc_back 0.0.0",
"rustc_driver 0.0.0",
"rustdoc 0.0.0",
]
[[package]]
name = "rustc-serialize"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc_back"
version = "0.0.0"
dependencies = [
"log 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
]
[[package]]
name = "rustc_bitflags"
version = "0.0.0"
[[package]]
name = "rustc_borrowck"
version = "0.0.0"
dependencies = [
"graphviz 0.0.0",
"log 0.0.0",
"rustc 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"rustc_mir 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_const_eval"
version = "0.0.0"
dependencies = [
"arena 0.0.0",
"graphviz 0.0.0",
"log 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_const_math"
version = "0.0.0"
dependencies = [
"log 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
]
[[package]]
name = "rustc_data_structures"
version = "0.0.0"
dependencies = [
"log 0.0.0",
"serialize 0.0.0",
]
[[package]]
name = "rustc_driver"
version = "0.0.0"
dependencies = [
"arena 0.0.0",
"flate 0.0.0",
"graphviz 0.0.0",
"log 0.0.0",
"proc_macro_plugin 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_borrowck 0.0.0",
"rustc_const_eval 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"rustc_incremental 0.0.0",
"rustc_lint 0.0.0",
"rustc_llvm 0.0.0",
"rustc_metadata 0.0.0",
"rustc_mir 0.0.0",
"rustc_passes 0.0.0",
"rustc_plugin 0.0.0",
"rustc_privacy 0.0.0",
"rustc_resolve 0.0.0",
"rustc_save_analysis 0.0.0",
"rustc_trans 0.0.0",
"rustc_typeck 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"syntax_ext 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_errors"
version = "0.0.0"
dependencies = [
"log 0.0.0",
"serialize 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_incremental"
version = "0.0.0"
dependencies = [
"graphviz 0.0.0",
"log 0.0.0",
"rustc 0.0.0",
"rustc_data_structures 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_lint"
version = "0.0.0"
dependencies = [
"log 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_const_eval 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_llvm"
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_bitflags 0.0.0",
]
[[package]]
name = "rustc_metadata"
version = "0.0.0"
dependencies = [
"flate 0.0.0",
"log 0.0.0",
"proc_macro 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"rustc_llvm 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"syntax_ext 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_mir"
version = "0.0.0"
dependencies = [
"graphviz 0.0.0",
"log 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_bitflags 0.0.0",
"rustc_const_eval 0.0.0",
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_passes"
version = "0.0.0"
dependencies = [
"log 0.0.0",
"rustc 0.0.0",
"rustc_const_eval 0.0.0",
"rustc_const_math 0.0.0",
"rustc_errors 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_platform_intrinsics"
version = "0.0.0"
[[package]]
name = "rustc_plugin"
version = "0.0.0"
dependencies = [
"log 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_bitflags 0.0.0",
"rustc_errors 0.0.0",
"rustc_metadata 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_privacy"
version = "0.0.0"
dependencies = [
"rustc 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_resolve"
version = "0.0.0"
dependencies = [
"arena 0.0.0",
"log 0.0.0",
"rustc 0.0.0",
"rustc_errors 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_save_analysis"
version = "0.0.0"
dependencies = [
"log 0.0.0",
"rustc 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_trans"
version = "0.0.0"
dependencies = [
"arena 0.0.0",
"flate 0.0.0",
"graphviz 0.0.0",
"log 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_const_eval 0.0.0",
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"rustc_incremental 0.0.0",
"rustc_llvm 0.0.0",
"rustc_platform_intrinsics 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_typeck"
version = "0.0.0"
dependencies = [
"arena 0.0.0",
"fmt_macros 0.0.0",
"log 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_const_eval 0.0.0",
"rustc_const_math 0.0.0",
"rustc_errors 0.0.0",
"rustc_platform_intrinsics 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_unicode"
version = "0.0.0"
dependencies = [
"core 0.0.0",
]
[[package]]
name = "rustdoc"
version = "0.0.0"
dependencies = [
"arena 0.0.0",
"build_helper 0.1.0",
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_const_eval 0.0.0",
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_driver 0.0.0",
"rustc_errors 0.0.0",
"rustc_lint 0.0.0",
"rustc_metadata 0.0.0",
"rustc_resolve 0.0.0",
"rustc_trans 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "serialize"
version = "0.0.0"
dependencies = [
"log 0.0.0",
]
[[package]]
name = "std"
version = "0.0.0"
dependencies = [
"alloc 0.0.0",
"alloc_jemalloc 0.0.0",
"alloc_system 0.0.0",
"build_helper 0.1.0",
"collections 0.0.0",
"compiler_builtins 0.0.0",
"core 0.0.0",
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.0.0",
"panic_abort 0.0.0",
"panic_unwind 0.0.0",
"rand 0.0.0",
"rustc_unicode 0.0.0",
"unwind 0.0.0",
]
[[package]]
name = "std_shim"
version = "0.1.0"
dependencies = [
"core 0.0.0",
"std 0.0.0",
]
[[package]]
name = "syntax"
version = "0.0.0"
dependencies = [
"log 0.0.0",
"rustc_bitflags 0.0.0",
"rustc_errors 0.0.0",
"serialize 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "syntax_ext"
version = "0.0.0"
dependencies = [
"fmt_macros 0.0.0",
"log 0.0.0",
"proc_macro 0.0.0",
"rustc_errors 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "syntax_pos"
version = "0.0.0"
dependencies = [
"serialize 0.0.0",
]
[[package]]
name = "term"
version = "0.0.0"
[[package]]
name = "test"
version = "0.0.0"
dependencies = [
"getopts 0.0.0",
"term 0.0.0",
]
[[package]]
name = "test_shim"
version = "0.1.0"
dependencies = [
"test 0.0.0",
]
[[package]]
name = "tidy"
version = "0.1.0"
[[package]]
name = "toml"
version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-bidi"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-normalization"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "url"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "dfcf5bcece56ef953b8ea042509e9dcbdfe97820b7e20d86beb53df30ed94978"
"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
"checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
"checksum gcc 0.3.38 (git+https://github.com/alexcrichton/gcc-rs)" = "<none>"
"checksum gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "553f11439bdefe755bf366b264820f1da70f3aaf3924e594b886beb9c831bcf5"
"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
"checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8"
"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
"checksum matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc3ad8109fa4b522f9b0cd81440422781f564aaf8c195de6b9d6642177ad0dd"
"checksum md5 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5539a8dee9b4ae308c9c406a379838b435a8f2c84cf9fedc6d5a576be9888db"
"checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3"
"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
"checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796"
"checksum unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c1f7ceb96afdfeedee42bade65a0d585a6a0106f681b6749c8ff4daa8df30b3f"
"checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172"
"checksum url 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ba5a45db1d2e0effb7a1c00cc73ffc63a973da8c7d1fcd5b46f24285ade6c54"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

13
src/Cargo.toml Normal file
View file

@ -0,0 +1,13 @@
[workspace]
members = [
"bootstrap",
"rustc",
"rustc/std_shim",
"rustc/test_shim",
"tools/cargotest",
"tools/compiletest",
"tools/error_index_generator",
"tools/linkchecker",
"tools/rustbook",
"tools/tidy",
]

180
src/bootstrap/Cargo.lock generated
View file

@ -1,180 +0,0 @@
[root]
name = "bootstrap"
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
"cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.31 (git+https://github.com/alexcrichton/gcc-rs)",
"getopts 0.2.14 (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.10 (registry+https://github.com/rust-lang/crates.io-index)",
"md5 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "aho-corasick"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "build_helper"
version = "0.1.0"
[[package]]
name = "cmake"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "filetime"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gcc"
version = "0.3.31"
source = "git+https://github.com/alexcrichton/gcc-rs#b8e2400883f1a2749b323354dad372cdd1c838c7"
[[package]]
name = "gcc"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "getopts"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "md5"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num_cpus"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "0.1.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-serialize"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "thread-id"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "toml"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "utf8-ranges"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b3fb52b09c1710b961acb35390d514be82e4ac96a9969a8e38565a29b878dc9"
"checksum cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "dfcf5bcece56ef953b8ea042509e9dcbdfe97820b7e20d86beb53df30ed94978"
"checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
"checksum gcc 0.3.31 (git+https://github.com/alexcrichton/gcc-rs)" = "<none>"
"checksum gcc 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)" = "cfe877476e53690ebb0ce7325d0bf43e198d9500291b54b3c65e518de5039b07"
"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "55f3730be7e803cf350d32061958171731c2395831fbd67a61083782808183e0"
"checksum md5 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5539a8dee9b4ae308c9c406a379838b435a8f2c84cf9fedc6d5a576be9888db"
"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
"checksum num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "51fedae97a05f7353612fe017ab705a37e6db8f4d67c5c6fe739a9e70d6eed09"
"checksum regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)" = "56b7ee9f764ecf412c6e2fff779bca4b22980517ae335a21aeaf4e32625a5df2"
"checksum regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "31040aad7470ad9d8c46302dcffba337bb4289ca5da2e3cd6e37b64109a85199"
"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
"checksum thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "55dd963dbaeadc08aa7266bf7f91c3154a7805e32bb94b820b769d2ef3b4744d"
"checksum toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "fcd27a04ca509aff336ba5eb2abc58d456f52c4ff64d9724d88acb85ead560b6"
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
"checksum winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4dfaaa8fbdaa618fa6914b59b2769d690dd7521920a18d84b42d254678dd5fd4"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

View file

@ -27,9 +27,10 @@ num_cpus = "0.2"
toml = "0.1"
getopts = "0.2"
rustc-serialize = "0.3"
winapi = "0.2"
kernel32-sys = "0.2"
gcc = { git = "https://github.com/alexcrichton/gcc-rs" }
libc = "0.2"
md5 = "0.1"
regex = "0.1.73"
[target.'cfg(windows)'.dependencies]
winapi = "0.2"
kernel32-sys = "0.2"

View file

@ -36,8 +36,9 @@ fn main() {
let args = env::args_os().skip(1).collect::<Vec<_>>();
// Detect whether or not we're a build script depending on whether --target
// is passed (a bit janky...)
let target = args.windows(2).find(|w| &*w[0] == "--target")
.and_then(|w| w[1].to_str());
let target = args.windows(2)
.find(|w| &*w[0] == "--target")
.and_then(|w| w[1].to_str());
let version = args.iter().find(|w| &**w == "-vV");
// Build scripts always use the snapshot compiler which is guaranteed to be
@ -55,23 +56,24 @@ fn main() {
} else {
("RUSTC_REAL", "RUSTC_LIBDIR")
};
let stage = env::var("RUSTC_STAGE").unwrap();
let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
let rustc = env::var_os(rustc).unwrap();
let libdir = env::var_os(libdir).unwrap();
let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
let mut dylib_path = bootstrap::util::dylib_path();
dylib_path.insert(0, PathBuf::from(libdir));
let mut cmd = Command::new(rustc);
cmd.args(&args)
.arg("--cfg").arg(format!("stage{}", stage))
.env(bootstrap::util::dylib_path_var(),
env::join_paths(&dylib_path).unwrap());
.arg("--cfg")
.arg(format!("stage{}", stage))
.env(bootstrap::util::dylib_path_var(),
env::join_paths(&dylib_path).unwrap());
if let Some(target) = target {
// The stage0 compiler has a special sysroot distinct from what we
// actually downloaded, so we just always pass the `--sysroot` option.
cmd.arg("--sysroot").arg(env::var_os("RUSTC_SYSROOT").unwrap());
cmd.arg("--sysroot").arg(env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set"));
// When we build Rust dylibs they're all intended for intermediate
// usage, so make sure we pass the -Cprefer-dynamic flag instead of
@ -101,11 +103,9 @@ fn main() {
// This... is a bit of a hack how we detect this. Ideally this
// information should be encoded in the crate I guess? Would likely
// require an RFC amendment to RFC 1513, however.
let is_panic_abort = args.windows(2).any(|a| {
&*a[0] == "--crate-name" && &*a[1] == "panic_abort"
});
// FIXME(stage0): remove this `stage != "0"` condition
if is_panic_abort && stage != "0" {
let is_panic_abort = args.windows(2)
.any(|a| &*a[0] == "--crate-name" && &*a[1] == "panic_abort");
if is_panic_abort {
cmd.arg("-C").arg("panic=abort");
}
@ -113,9 +113,11 @@ fn main() {
// code.
if env::var("RUSTC_DEBUGINFO") == Ok("true".to_string()) {
cmd.arg("-g");
} else if env::var("RUSTC_DEBUGINFO_LINES") == Ok("true".to_string()) {
cmd.arg("-Cdebuginfo=1");
}
let debug_assertions = match env::var("RUSTC_DEBUG_ASSERTIONS") {
Ok(s) => if s == "true" {"y"} else {"n"},
Ok(s) => if s == "true" { "y" } else { "n" },
Err(..) => "n",
};
cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions));

View file

@ -20,21 +20,23 @@ use std::path::PathBuf;
fn main() {
let args = env::args_os().skip(1).collect::<Vec<_>>();
let rustdoc = env::var_os("RUSTDOC_REAL").unwrap();
let libdir = env::var_os("RUSTC_LIBDIR").unwrap();
let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set");
let libdir = env::var_os("RUSTC_LIBDIR").expect("RUSTC_LIBDIR was not set");
let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
let mut dylib_path = bootstrap::util::dylib_path();
dylib_path.insert(0, PathBuf::from(libdir));
let mut cmd = Command::new(rustdoc);
cmd.args(&args)
.arg("--cfg").arg(format!("stage{}", env::var("RUSTC_STAGE").unwrap()))
.arg("--cfg").arg("dox")
.env(bootstrap::util::dylib_path_var(),
env::join_paths(&dylib_path).unwrap());
.arg("--cfg")
.arg(format!("stage{}", stage))
.arg("--cfg")
.arg("dox")
.env(bootstrap::util::dylib_path_var(),
env::join_paths(&dylib_path).unwrap());
std::process::exit(match cmd.status() {
Ok(s) => s.code().unwrap_or(1),
Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
})
}

View file

@ -131,7 +131,8 @@ def stage0_data(rust_root):
def format_build_time(duration):
return str(datetime.timedelta(seconds=int(duration)))
class RustBuild:
class RustBuild(object):
def download_stage0(self):
cache_dst = os.path.join(self.build_dir, "cache")
rustc_cache = os.path.join(cache_dst, self.stage0_rustc_date())
@ -142,7 +143,7 @@ class RustBuild:
os.makedirs(cargo_cache)
if self.rustc().startswith(self.bin_root()) and \
(not os.path.exists(self.rustc()) or self.rustc_out_of_date()):
(not os.path.exists(self.rustc()) or self.rustc_out_of_date()):
if os.path.exists(self.bin_root()):
shutil.rmtree(self.bin_root())
channel = self.stage0_rustc_channel()
@ -165,7 +166,7 @@ class RustBuild:
f.write(self.stage0_rustc_date())
if self.cargo().startswith(self.bin_root()) and \
(not os.path.exists(self.cargo()) or self.cargo_out_of_date()):
(not os.path.exists(self.cargo()) or self.cargo_out_of_date()):
channel = self.stage0_cargo_channel()
filename = "cargo-{}-{}.tar.gz".format(channel, self.build)
url = "https://static.rust-lang.org/cargo-dist/" + self.stage0_cargo_date()
@ -238,8 +239,8 @@ class RustBuild:
def get_string(self, line):
start = line.find('"')
end = start + 1 + line[start+1:].find('"')
return line[start+1:end]
end = start + 1 + line[start + 1:].find('"')
return line[start + 1:end]
def exe_suffix(self):
if sys.platform == 'win32':
@ -269,6 +270,7 @@ class RustBuild:
sys.exit(ret)
def build_triple(self):
default_encoding = sys.getdefaultencoding()
config = self.get_toml('build')
if config:
return config
@ -276,8 +278,8 @@ class RustBuild:
if config:
return config
try:
ostype = subprocess.check_output(['uname', '-s']).strip()
cputype = subprocess.check_output(['uname', '-m']).strip()
ostype = subprocess.check_output(['uname', '-s']).strip().decode(default_encoding)
cputype = subprocess.check_output(['uname', '-m']).strip().decode(default_encoding)
except (subprocess.CalledProcessError, WindowsError):
if sys.platform == 'win32':
return 'x86_64-pc-windows-msvc'
@ -289,7 +291,8 @@ class RustBuild:
# Darwin's `uname -s` lies and always returns i386. We have to use
# sysctl instead.
if ostype == 'Darwin' and cputype == 'i686':
sysctl = subprocess.check_output(['sysctl', 'hw.optional.x86_64'])
args = ['sysctl', 'hw.optional.x86_64']
sysctl = subprocess.check_output(args).decode(default_encoding)
if ': 1' in sysctl:
cputype = 'x86_64'

View file

@ -13,19 +13,44 @@
//! This file implements the various regression test suites that we execute on
//! our CI.
use std::collections::{HashMap, HashSet};
use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::fs;
use std::path::{PathBuf, Path};
use std::process::Command;
use build_helper::output;
use rustc_serialize::json;
use {Build, Compiler, Mode};
use util::{self, dylib_path, dylib_path_var};
const ADB_TEST_DIR: &'static str = "/data/tmp";
#[derive(RustcDecodable)]
struct Output {
packages: Vec<Package>,
resolve: Resolve,
}
#[derive(RustcDecodable)]
struct Package {
id: String,
name: String,
source: Option<String>,
}
#[derive(RustcDecodable)]
struct Resolve {
nodes: Vec<ResolveNode>,
}
#[derive(RustcDecodable)]
struct ResolveNode {
id: String,
dependencies: Vec<String>,
}
/// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
///
/// This tool in `src/tools` will verify the validity of all our links in the
@ -108,6 +133,10 @@ pub fn compiletest(build: &Build,
cmd.arg("--host").arg(compiler.host);
cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.config.build));
if let Some(nodejs) = build.config.nodejs.as_ref() {
cmd.arg("--nodejs").arg(nodejs);
}
let mut flags = vec!["-Crpath".to_string()];
if build.config.rust_optimize_tests {
flags.push("-O".to_string());
@ -185,7 +214,7 @@ pub fn compiletest(build: &Build,
}
}
}
build.add_bootstrap_key(compiler, &mut cmd);
build.add_bootstrap_key(&mut cmd);
cmd.arg("--adb-path").arg("adb");
cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
@ -259,56 +288,74 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) {
/// It essentially is the driver for running `cargo test`.
///
/// Currently this runs all tests for a DAG by passing a bunch of `-p foo`
/// arguments, and those arguments are discovered from `Cargo.lock`.
/// arguments, and those arguments are discovered from `cargo metadata`.
pub fn krate(build: &Build,
compiler: &Compiler,
target: &str,
mode: Mode) {
let (name, path, features) = match mode {
Mode::Libstd => ("libstd", "src/rustc/std_shim", build.std_features()),
Mode::Libtest => ("libtest", "src/rustc/test_shim", String::new()),
Mode::Librustc => ("librustc", "src/rustc", build.rustc_features()),
let (name, path, features, root) = match mode {
Mode::Libstd => {
("libstd", "src/rustc/std_shim", build.std_features(), "std_shim")
}
Mode::Libtest => {
("libtest", "src/rustc/test_shim", String::new(), "test_shim")
}
Mode::Librustc => {
("librustc", "src/rustc", build.rustc_features(), "rustc-main")
}
_ => panic!("can only test libraries"),
};
println!("Testing {} stage{} ({} -> {})", name, compiler.stage,
compiler.host, target);
// Run `cargo metadata` to figure out what crates we're testing.
//
// Down below we're going to call `cargo test`, but to test the right set
// of packages we're going to have to know what `-p` arguments to pass it
// to know what crates to test. Here we run `cargo metadata` to learn about
// the dependency graph and what `-p` arguments there are.
let mut cargo = Command::new(&build.cargo);
cargo.arg("metadata")
.arg("--manifest-path").arg(build.src.join(path).join("Cargo.toml"));
let output = output(&mut cargo);
let output: Output = json::decode(&output).unwrap();
let id2pkg = output.packages.iter()
.map(|pkg| (&pkg.id, pkg))
.collect::<HashMap<_, _>>();
let id2deps = output.resolve.nodes.iter()
.map(|node| (&node.id, &node.dependencies))
.collect::<HashMap<_, _>>();
// Build up the base `cargo test` command.
//
// Pass in some standard flags then iterate over the graph we've discovered
// in `cargo metadata` with the maps above and figure out what `-p`
// arguments need to get passed.
let mut cargo = build.cargo(compiler, mode, target, "test");
cargo.arg("--manifest-path")
.arg(build.src.join(path).join("Cargo.toml"))
.arg("--features").arg(features);
// Generate a list of `-p` arguments to pass to the `cargo test` invocation
// by crawling the corresponding Cargo.lock file.
let lockfile = build.src.join(path).join("Cargo.lock");
let mut contents = String::new();
t!(t!(File::open(&lockfile)).read_to_string(&mut contents));
let mut lines = contents.lines();
while let Some(line) = lines.next() {
let prefix = "name = \"";
if !line.starts_with(prefix) {
let mut visited = HashSet::new();
let root_pkg = output.packages.iter().find(|p| p.name == root).unwrap();
let mut next = vec![&root_pkg.id];
while let Some(id) = next.pop() {
// Skip any packages with sources listed, as these come from crates.io
// and we shouldn't be testing them.
if id2pkg[id].source.is_some() {
continue
}
lines.next(); // skip `version = ...`
// skip crates.io or otherwise non-path crates
if let Some(line) = lines.next() {
if line.starts_with("source") {
continue
}
}
let crate_name = &line[prefix.len()..line.len() - 1];
// Right now jemalloc is our only target-specific crate in the sense
// that it's not present on all platforms. Custom skip it here for now,
// but if we add more this probably wants to get more generalized.
if crate_name.contains("jemalloc") {
continue
if !id.contains("jemalloc") {
cargo.arg("-p").arg(&id2pkg[id].name);
}
for dep in id2deps[id] {
if visited.insert(dep) {
next.push(dep);
}
}
cargo.arg("-p").arg(crate_name);
}
// The tests are going to run with the *target* libraries, so we need to
@ -323,6 +370,9 @@ pub fn krate(build: &Build,
if target.contains("android") {
build.run(cargo.arg("--no-run"));
krate_android(build, compiler, target, mode);
} else if target.contains("emscripten") {
build.run(cargo.arg("--no-run"));
krate_emscripten(build, compiler, target, mode);
} else {
cargo.args(&build.flags.args);
build.run(&mut cargo);
@ -371,6 +421,35 @@ fn krate_android(build: &Build,
}
}
fn krate_emscripten(build: &Build,
compiler: &Compiler,
target: &str,
mode: Mode) {
let mut tests = Vec::new();
let out_dir = build.cargo_out(compiler, mode, target);
find_tests(&out_dir, target, &mut tests);
find_tests(&out_dir.join("deps"), target, &mut tests);
for test in tests {
let test_file_name = test.to_string_lossy().into_owned();
println!("running {}", test_file_name);
let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured");
let status = Command::new(nodejs)
.arg(&test_file_name)
.stderr(::std::process::Stdio::inherit())
.status();
match status {
Ok(status) => {
if !status.success() {
panic!("some tests failed");
}
}
Err(e) => panic!(format!("failed to execute command: {}", e)),
};
}
}
fn find_tests(dir: &Path,
target: &str,
dst: &mut Vec<PathBuf>) {
@ -381,7 +460,8 @@ fn find_tests(dir: &Path,
}
let filename = e.file_name().into_string().unwrap();
if (target.contains("windows") && filename.ends_with(".exe")) ||
(!target.contains("windows") && !filename.contains(".")) {
(!target.contains("windows") && !filename.contains(".")) ||
(target.contains("emscripten") && filename.contains(".js")){
dst.push(e.path());
}
}

View file

@ -25,7 +25,7 @@ use std::process::Command;
use build_helper::output;
use filetime::FileTime;
use util::{exe, staticlib, libdir, mtime, is_dylib, copy};
use util::{exe, libdir, mtime, is_dylib, copy};
use {Build, Compiler, Mode};
/// Build the standard library.
@ -40,20 +40,6 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
let libdir = build.sysroot_libdir(compiler, target);
let _ = fs::remove_dir_all(&libdir);
t!(fs::create_dir_all(&libdir));
// FIXME(stage0) remove this `if` after the next snapshot
// The stage0 compiler still passes the `-lcompiler-rt` flag to the linker but now `bootstrap`
// never builds a `libcopmiler-rt.a`! We'll fill the hole by simply copying stage0's
// `libcompiler-rt.a` to where the stage1's one is expected (though we could as well just use
// an empty `.a` archive). Note that the symbols of that stage0 `libcompiler-rt.a` won't make
// it to the final binary because now `libcore.rlib` also contains the symbols that
// `libcompiler-rt.a` provides. Since that rlib appears first in the linker arguments, its
// symbols are used instead of `libcompiler-rt.a`'s.
if compiler.stage == 0 {
let rtlib = &staticlib("compiler-rt", target);
let src = build.rustc.parent().unwrap().parent().unwrap().join("lib").join("rustlib")
.join(target).join("lib").join(rtlib);
copy(&src, &libdir.join(rtlib));
}
// Some platforms have startup objects that may be required to produce the
// libstd dynamic library, for example.
@ -104,16 +90,16 @@ pub fn std_link(build: &Build,
add_to_sysroot(&out_dir, &libdir);
if target.contains("musl") && !target.contains("mips") {
copy_musl_third_party_objects(build, &libdir);
copy_musl_third_party_objects(build, target, &libdir);
}
}
/// Copies the crt(1,i,n).o startup objects
///
/// Only required for musl targets that statically link to libc
fn copy_musl_third_party_objects(build: &Build, into: &Path) {
fn copy_musl_third_party_objects(build: &Build, target: &str, into: &Path) {
for &obj in &["crt1.o", "crti.o", "crtn.o"] {
copy(&build.config.musl_root.as_ref().unwrap().join("lib").join(obj), &into.join(obj));
copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj));
}
}
@ -133,7 +119,7 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) {
for file in t!(fs::read_dir(build.src.join("src/rtstartup"))) {
let file = t!(file);
let mut cmd = Command::new(&compiler_path);
build.add_bootstrap_key(&compiler, &mut cmd);
build.add_bootstrap_key(&mut cmd);
build.run(cmd.arg("--target").arg(target)
.arg("--emit=obj")
.arg("--out-dir").arg(into)
@ -199,7 +185,6 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
cargo.env("CFG_RELEASE", &build.release)
.env("CFG_RELEASE_CHANNEL", &build.config.channel)
.env("CFG_VERSION", &build.version)
.env("CFG_BOOTSTRAP_KEY", &build.bootstrap_key)
.env("CFG_PREFIX", build.config.prefix.clone().unwrap_or(String::new()))
.env("CFG_LIBDIR_RELATIVE", "lib");

View file

@ -56,6 +56,7 @@ pub struct Config {
pub rust_codegen_units: u32,
pub rust_debug_assertions: bool,
pub rust_debuginfo: bool,
pub rust_debuginfo_lines: bool,
pub rust_rpath: bool,
pub rustc_default_linker: Option<String>,
pub rustc_default_ar: Option<String>,
@ -79,6 +80,9 @@ pub struct Config {
// Fallback musl-root for all targets
pub musl_root: Option<PathBuf>,
pub prefix: Option<String>,
pub docdir: Option<String>,
pub libdir: Option<String>,
pub mandir: Option<String>,
pub codegen_tests: bool,
pub nodejs: Option<PathBuf>,
}
@ -117,6 +121,7 @@ struct Build {
rustc: Option<String>,
compiler_docs: Option<bool>,
docs: Option<bool>,
submodules: Option<bool>,
}
/// TOML representation of how the LLVM build is configured.
@ -137,6 +142,7 @@ struct Rust {
codegen_units: Option<u32>,
debug_assertions: Option<bool>,
debuginfo: Option<bool>,
debuginfo_lines: Option<bool>,
debug_jemalloc: Option<bool>,
use_jemalloc: Option<bool>,
backtrace: Option<bool>,
@ -158,6 +164,7 @@ struct TomlTarget {
cc: Option<String>,
cxx: Option<String>,
android_ndk: Option<String>,
musl_root: Option<String>,
}
impl Config {
@ -221,6 +228,7 @@ impl Config {
config.cargo = build.cargo.map(PathBuf::from);
set(&mut config.compiler_docs, build.compiler_docs);
set(&mut config.docs, build.docs);
set(&mut config.submodules, build.submodules);
if let Some(ref llvm) = toml.llvm {
set(&mut config.ccache, llvm.ccache);
@ -233,6 +241,7 @@ impl Config {
if let Some(ref rust) = toml.rust {
set(&mut config.rust_debug_assertions, rust.debug_assertions);
set(&mut config.rust_debuginfo, rust.debuginfo);
set(&mut config.rust_debuginfo_lines, rust.debuginfo_lines);
set(&mut config.rust_optimize, rust.optimize);
set(&mut config.rust_optimize_tests, rust.optimize_tests);
set(&mut config.rust_debuginfo_tests, rust.debuginfo_tests);
@ -268,6 +277,7 @@ impl Config {
}
target.cxx = cfg.cxx.clone().map(PathBuf::from);
target.cc = cfg.cc.clone().map(PathBuf::from);
target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
config.target_config.insert(triple.clone(), target);
}
@ -322,6 +332,7 @@ impl Config {
("OPTIMIZE", self.rust_optimize),
("DEBUG_ASSERTIONS", self.rust_debug_assertions),
("DEBUGINFO", self.rust_debuginfo),
("DEBUGINFO_LINES", self.rust_debuginfo_lines),
("JEMALLOC", self.use_jemalloc),
("DEBUG_JEMALLOC", self.debug_jemalloc),
("RPATH", self.rust_rpath),
@ -345,6 +356,36 @@ impl Config {
"CFG_MUSL_ROOT" if value.len() > 0 => {
self.musl_root = Some(PathBuf::from(value));
}
"CFG_MUSL_ROOT_X86_64" if value.len() > 0 => {
let target = "x86_64-unknown-linux-musl".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
target.musl_root = Some(PathBuf::from(value));
}
"CFG_MUSL_ROOT_I686" if value.len() > 0 => {
let target = "i686-unknown-linux-musl".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
target.musl_root = Some(PathBuf::from(value));
}
"CFG_MUSL_ROOT_ARM" if value.len() > 0 => {
let target = "arm-unknown-linux-musleabi".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
target.musl_root = Some(PathBuf::from(value));
}
"CFG_MUSL_ROOT_ARMHF" if value.len() > 0 => {
let target = "arm-unknown-linux-musleabihf".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
target.musl_root = Some(PathBuf::from(value));
}
"CFG_MUSL_ROOT_ARMV7" if value.len() > 0 => {
let target = "armv7-unknown-linux-musleabihf".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
target.musl_root = Some(PathBuf::from(value));
}
"CFG_DEFAULT_AR" if value.len() > 0 => {
self.rustc_default_ar = Some(value.to_string());
}
@ -357,6 +398,15 @@ impl Config {
"CFG_PREFIX" => {
self.prefix = Some(value.to_string());
}
"CFG_DOCDIR" => {
self.docdir = Some(value.to_string());
}
"CFG_LIBDIR" => {
self.libdir = Some(value.to_string());
}
"CFG_MANDIR" => {
self.mandir = Some(value.to_string());
}
"CFG_LLVM_ROOT" if value.len() > 0 => {
let target = self.target_config.entry(self.build.clone())
.or_insert(Target::default());
@ -396,9 +446,6 @@ impl Config {
self.rustc = Some(PathBuf::from(value).join("bin/rustc"));
self.cargo = Some(PathBuf::from(value).join("bin/cargo"));
}
"CFG_NODEJS" if value.len() > 0 => {
self.nodejs = Some(PathBuf::from(value));
}
_ => {}
}
}

View file

@ -76,6 +76,9 @@
# library and facade crates.
#compiler-docs = false
# Indicate whether submodules are managed and updated automatically.
#submodules = true
# =============================================================================
# Options for compiling Rust code itself
# =============================================================================
@ -96,6 +99,9 @@
# Whether or not debuginfo is emitted
#debuginfo = false
# Whether or not line number debug information is emitted
#debuginfo-lines = false
# Whether or not jemalloc is built and enabled
#use-jemalloc = true

View file

@ -25,9 +25,8 @@ use std::process::Command;
use {Build, Compiler};
use util::{cp_r, libdir, is_dylib, cp_filtered, copy};
use regex::{RegexSet, quote};
fn package_vers(build: &Build) -> &str {
pub fn package_vers(build: &Build) -> &str {
match &build.config.channel[..] {
"stable" => &build.release,
"beta" => "beta",
@ -40,7 +39,7 @@ fn distdir(build: &Build) -> PathBuf {
build.out.join("dist")
}
fn tmpdir(build: &Build) -> PathBuf {
pub fn tmpdir(build: &Build) -> PathBuf {
build.out.join("tmp/dist")
}
@ -315,49 +314,31 @@ pub fn rust_src(build: &Build) {
"mk"
];
// Exclude paths matching these wildcard expressions
let excludes = [
// exclude-vcs
"CVS", "RCS", "SCCS", ".git", ".gitignore", ".gitmodules", ".gitattributes", ".cvsignore",
".svn", ".arch-ids", "{arch}", "=RELEASE-ID", "=meta-update", "=update", ".bzr",
".bzrignore", ".bzrtags", ".hg", ".hgignore", ".hgrags", "_darcs",
// extensions
"*~", "*.pyc",
// misc
"llvm/test/*/*.ll",
"llvm/test/*/*.td",
"llvm/test/*/*.s",
"llvm/test/*/*/*.ll",
"llvm/test/*/*/*.td",
"llvm/test/*/*/*.s"
];
// Construct a set of regexes for efficiently testing whether paths match one of the above
// expressions.
let regex_set = t!(RegexSet::new(
// This converts a wildcard expression to a regex
excludes.iter().map(|&s| {
// Prefix ensures that matching starts on a path separator boundary
r"^(.*[\\/])?".to_owned() + (
// Escape the expression to produce a regex matching exactly that string
&quote(s)
// Replace slashes with a pattern matching either forward or backslash
.replace(r"/", r"[\\/]")
// Replace wildcards with a pattern matching a single path segment, ie. containing
// no slashes.
.replace(r"\*", r"[^\\/]*")
// Suffix anchors to the end of the path
) + "$"
})
));
// Create a filter which skips files which match the regex set or contain invalid unicode
let filter_fn = move |path: &Path| {
if let Some(path) = path.to_str() {
!regex_set.is_match(path)
} else {
false
let spath = match path.to_str() {
Some(path) => path,
None => return false,
};
if spath.ends_with("~") || spath.ends_with(".pyc") {
return false
}
if spath.contains("llvm/test") || spath.contains("llvm\\test") {
if spath.ends_with(".ll") ||
spath.ends_with(".td") ||
spath.ends_with(".s") {
return false
}
}
let excludes = [
"CVS", "RCS", "SCCS", ".git", ".gitignore", ".gitmodules",
".gitattributes", ".cvsignore", ".svn", ".arch-ids", "{arch}",
"=RELEASE-ID", "=meta-update", "=update", ".bzr", ".bzrignore",
".bzrtags", ".hg", ".hgignore", ".hgrags", "_darcs",
];
!path.iter()
.map(|s| s.to_str().unwrap())
.any(|s| excludes.contains(&s))
};
// Copy the directories using our filter
@ -418,7 +399,7 @@ fn chmod(_path: &Path, _perms: u32) {}
// We have to run a few shell scripts, which choke quite a bit on both `\`
// characters and on `C:\` paths, so normalize both of them away.
fn sanitize_sh(path: &Path) -> String {
pub fn sanitize_sh(path: &Path) -> String {
let path = path.to_str().unwrap().replace("\\", "/");
return change_drive(&path).unwrap_or(path);

61
src/bootstrap/install.rs Normal file
View file

@ -0,0 +1,61 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Implementation of the install aspects of the compiler.
//!
//! This module is responsible for installing the standard library,
//! compiler, and documentation.
use std::fs;
use std::borrow::Cow;
use std::path::Path;
use std::process::Command;
use Build;
use dist::{package_vers, sanitize_sh, tmpdir};
/// Installs everything.
pub fn install(build: &Build, stage: u32, host: &str) {
let prefix = build.config.prefix.as_ref().clone().map(|x| Path::new(x))
.unwrap_or(Path::new("/usr/local"));
let docdir = build.config.docdir.as_ref().clone().map(|x| Cow::Borrowed(Path::new(x)))
.unwrap_or(Cow::Owned(prefix.join("share/doc/rust")));
let libdir = build.config.libdir.as_ref().clone().map(|x| Cow::Borrowed(Path::new(x)))
.unwrap_or(Cow::Owned(prefix.join("lib")));
let mandir = build.config.mandir.as_ref().clone().map(|x| Cow::Borrowed(Path::new(x)))
.unwrap_or(Cow::Owned(prefix.join("share/man")));
let empty_dir = build.out.join("tmp/empty_dir");
t!(fs::create_dir_all(&empty_dir));
if build.config.docs {
install_sh(&build, "docs", "rust-docs", stage, host, prefix,
&docdir, &libdir, &mandir, &empty_dir);
}
install_sh(&build, "std", "rust-std", stage, host, prefix,
&docdir, &libdir, &mandir, &empty_dir);
install_sh(&build, "rustc", "rustc", stage, host, prefix,
&docdir, &libdir, &mandir, &empty_dir);
t!(fs::remove_dir_all(&empty_dir));
}
fn install_sh(build: &Build, package: &str, name: &str, stage: u32, host: &str,
prefix: &Path, docdir: &Path, libdir: &Path, mandir: &Path, empty_dir: &Path) {
println!("Install {} stage{} ({})", package, stage, host);
let package_name = format!("{}-{}-{}", name, package_vers(build), host);
let mut cmd = Command::new("sh");
cmd.current_dir(empty_dir)
.arg(sanitize_sh(&tmpdir(build).join(&package_name).join("install.sh")))
.arg(format!("--prefix={}", sanitize_sh(prefix)))
.arg(format!("--docdir={}", sanitize_sh(docdir)))
.arg(format!("--libdir={}", sanitize_sh(libdir)))
.arg(format!("--mandir={}", sanitize_sh(mandir)))
.arg("--disable-ldconfig");
build.run(&mut cmd);
}

View file

@ -26,7 +26,6 @@ extern crate md5;
extern crate num_cpus;
extern crate rustc_serialize;
extern crate toml;
extern crate regex;
use std::collections::HashMap;
use std::env;
@ -62,6 +61,7 @@ mod config;
mod dist;
mod doc;
mod flags;
mod install;
mod native;
mod sanity;
mod step;
@ -220,14 +220,14 @@ impl Build {
sanity::check(self);
self.verbose("collecting channel variables");
channel::collect(self);
// If local-rust is the same as the current version, then force a local-rebuild
// If local-rust is the same major.minor as the current version, then force a local-rebuild
let local_version_verbose = output(
Command::new(&self.rustc).arg("--version").arg("--verbose"));
let local_release = local_version_verbose
.lines().filter(|x| x.starts_with("release:"))
.next().unwrap().trim_left_matches("release:").trim();
if local_release == self.release {
self.verbose(&format!("auto-detected local-rebuild {}", self.release));
if local_release.split('.').take(2).eq(self.release.split('.').take(2)) {
self.verbose(&format!("auto-detected local-rebuild {}", local_release));
self.local_rebuild = true;
}
self.verbose("updating submodules");
@ -243,7 +243,14 @@ impl Build {
// Almost all of these are simple one-liners that shell out to the
// corresponding functionality in the extra modules, where more
// documentation can be found.
for target in step::all(self) {
let steps = step::all(self);
self.verbose("bootstrap build plan:");
for step in &steps {
self.verbose(&format!("{:?}", step));
}
for target in steps {
let doc_out = self.out.join(&target.target).join("doc");
match target.src {
Llvm { _dummy } => {
@ -446,6 +453,8 @@ impl Build {
DistStd { compiler } => dist::std(self, &compiler, target.target),
DistSrc { _dummy } => dist::rust_src(self),
Install { stage } => install::install(self, stage, target.target),
DebuggerScripts { stage } => {
let compiler = Compiler::new(stage, target.target);
dist::debugger_scripts(self,
@ -550,12 +559,23 @@ impl Build {
continue
}
// `submodule.path` is the relative path to a submodule (from the repository root)
// `submodule_path` is the path to a submodule from the cwd
// use `submodule.path` when e.g. executing a submodule specific command from the
// repository root
// use `submodule_path` when e.g. executing a normal git command for the submodule
// (set via `current_dir`)
let submodule_path = self.src.join(submodule.path);
match submodule.state {
State::MaybeDirty => {
// drop staged changes
self.run(git().arg("-C").arg(submodule.path).args(&["reset", "--hard"]));
self.run(git().current_dir(&submodule_path)
.args(&["reset", "--hard"]));
// drops unstaged changes
self.run(git().arg("-C").arg(submodule.path).args(&["clean", "-fdx"]));
self.run(git().current_dir(&submodule_path)
.args(&["clean", "-fdx"]));
},
State::NotInitialized => {
self.run(git_submodule().arg("init").arg(submodule.path));
@ -564,8 +584,10 @@ impl Build {
State::OutOfSync => {
// drops submodule commits that weren't reported to the (outer) git repository
self.run(git_submodule().arg("update").arg(submodule.path));
self.run(git().arg("-C").arg(submodule.path).args(&["reset", "--hard"]));
self.run(git().arg("-C").arg(submodule.path).args(&["clean", "-fdx"]));
self.run(git().current_dir(&submodule_path)
.args(&["reset", "--hard"]));
self.run(git().current_dir(&submodule_path)
.args(&["clean", "-fdx"]));
},
}
}
@ -627,6 +649,7 @@ impl Build {
.env("RUSTC_REAL", self.compiler_path(compiler))
.env("RUSTC_STAGE", stage.to_string())
.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string())
.env("RUSTC_DEBUGINFO_LINES", self.config.rust_debuginfo_lines.to_string())
.env("RUSTC_CODEGEN_UNITS",
self.config.rust_codegen_units.to_string())
.env("RUSTC_DEBUG_ASSERTIONS",
@ -640,7 +663,7 @@ impl Build {
.env("RUSTDOC_REAL", self.rustdoc(compiler))
.env("RUSTC_FLAGS", self.rustc_flags(target).join(" "));
self.add_bootstrap_key(compiler, &mut cargo);
self.add_bootstrap_key(&mut cargo);
// Specify some various options for build scripts used throughout
// the build.
@ -652,12 +675,6 @@ impl Build {
.env(format!("CFLAGS_{}", target), self.cflags(target).join(" "));
}
// If we're building for OSX, inform the compiler and the linker that
// we want to build a compiler runnable on 10.7
if target.contains("apple-darwin") {
cargo.env("MACOSX_DEPLOYMENT_TARGET", "10.7");
}
// Environment variables *required* needed throughout the build
//
// FIXME: should update code to not require this env var
@ -855,16 +872,11 @@ impl Build {
}
/// Adds the compiler's bootstrap key to the environment of `cmd`.
fn add_bootstrap_key(&self, compiler: &Compiler, cmd: &mut Command) {
// In stage0 we're using a previously released stable compiler, so we
// use the stage0 bootstrap key. Otherwise we use our own build's
// bootstrap key.
let bootstrap_key = if compiler.is_snapshot(self) && !self.local_rebuild {
&self.bootstrap_key_stage0
} else {
&self.bootstrap_key
};
cmd.env("RUSTC_BOOTSTRAP_KEY", bootstrap_key);
fn add_bootstrap_key(&self, cmd: &mut Command) {
cmd.env("RUSTC_BOOTSTRAP", "");
// FIXME: Transitionary measure to bootstrap using the old bootstrap logic.
// Remove this once the bootstrap compiler uses the new login in Issue #36548.
cmd.env("RUSTC_BOOTSTRAP_KEY", "62b3e239");
}
/// Returns the compiler's libdir where it stores the dynamic libraries that
@ -926,7 +938,6 @@ impl Build {
// LLVM/jemalloc/etc are all properly compiled.
if target.contains("apple-darwin") {
base.push("-stdlib=libc++".into());
base.push("-mmacosx-version-min=10.7".into());
}
// This is a hack, because newer binutils broke things on some vms/distros
// (i.e., linking against unknown relocs disabled by the following flag)
@ -950,7 +961,11 @@ impl Build {
/// Returns the path to the C++ compiler for the target specified, may panic
/// if no C++ compiler was configured for the target.
fn cxx(&self, target: &str) -> &Path {
self.cxx[target].path()
match self.cxx.get(target) {
Some(p) => p.path(),
None => panic!("\n\ntarget `{}` is not configured as a host,
only as a target\n\n", target),
}
}
/// Returns flags to pass to the compiler to generate code for `target`.
@ -963,7 +978,8 @@ impl Build {
// than an entry here.
let mut base = Vec::new();
if target != self.config.build && !target.contains("msvc") {
if target != self.config.build && !target.contains("msvc") &&
!target.contains("emscripten") {
base.push(format!("-Clinker={}", self.cc(target).display()));
}
return base
@ -971,7 +987,8 @@ impl Build {
/// Returns the "musl root" for this `target`, if defined
fn musl_root(&self, target: &str) -> Option<&Path> {
self.config.target_config[target].musl_root.as_ref()
self.config.target_config.get(target)
.and_then(|t| t.musl_root.as_ref())
.or(self.config.musl_root.as_ref())
.map(|p| &**p)
}

View file

@ -51,6 +51,12 @@ check-cargotest:
$(Q)$(BOOTSTRAP) --step check-cargotest
dist:
$(Q)$(BOOTSTRAP) --step dist
install:
ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER)))
$(Q)echo "'sudo make install' is not supported currently."
else
$(Q)$(BOOTSTRAP) --step install
endif
tidy:
$(Q)$(BOOTSTRAP) --step check-tidy --stage 0

View file

@ -18,9 +18,10 @@
//! LLVM and compiler-rt are essentially just wired up to everything else to
//! ensure that they're always in place if needed.
use std::fs::{self, File};
use std::io::{Read, Write};
use std::path::Path;
use std::process::Command;
use std::fs::{self, File};
use build_helper::output;
use cmake;
@ -43,11 +44,17 @@ pub fn llvm(build: &Build, target: &str) {
// artifacts are missing) then we keep going, otherwise we bail out.
let dst = build.llvm_out(target);
let stamp = build.src.join("src/rustllvm/llvm-auto-clean-trigger");
let mut stamp_contents = String::new();
t!(t!(File::open(&stamp)).read_to_string(&mut stamp_contents));
let done_stamp = dst.join("llvm-finished-building");
build.clear_if_dirty(&dst, &stamp);
if fs::metadata(&done_stamp).is_ok() {
return
if done_stamp.exists() {
let mut done_contents = String::new();
t!(t!(File::open(&done_stamp)).read_to_string(&mut done_contents));
if done_contents == stamp_contents {
return
}
}
drop(fs::remove_dir_all(&dst));
println!("Building LLVM for {}", target);
@ -65,7 +72,7 @@ pub fn llvm(build: &Build, target: &str) {
.out_dir(&dst)
.profile(if build.config.llvm_optimize {"Release"} else {"Debug"})
.define("LLVM_ENABLE_ASSERTIONS", assertions)
.define("LLVM_TARGETS_TO_BUILD", "X86;ARM;AArch64;Mips;PowerPC;SystemZ")
.define("LLVM_TARGETS_TO_BUILD", "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend")
.define("LLVM_INCLUDE_EXAMPLES", "OFF")
.define("LLVM_INCLUDE_TESTS", "OFF")
.define("LLVM_INCLUDE_DOCS", "OFF")
@ -73,7 +80,9 @@ pub fn llvm(build: &Build, target: &str) {
.define("WITH_POLLY", "OFF")
.define("LLVM_ENABLE_TERMINFO", "OFF")
.define("LLVM_ENABLE_LIBEDIT", "OFF")
.define("LLVM_PARALLEL_COMPILE_JOBS", build.jobs().to_string());
.define("LLVM_PARALLEL_COMPILE_JOBS", build.jobs().to_string())
.define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
.define("LLVM_DEFAULT_TARGET_TRIPLE", target);
if target.starts_with("i686") {
cfg.define("LLVM_BUILD_32_BITS", "ON");
@ -86,9 +95,7 @@ pub fn llvm(build: &Build, target: &str) {
// actually exists most of the time in normal installs of LLVM.
let host = build.llvm_out(&build.config.build).join("bin/llvm-tblgen");
cfg.define("CMAKE_CROSSCOMPILING", "True")
.define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
.define("LLVM_TABLEGEN", &host)
.define("LLVM_DEFAULT_TARGET_TRIPLE", target);
.define("LLVM_TABLEGEN", &host);
}
// MSVC handles compiler business itself
@ -114,7 +121,7 @@ pub fn llvm(build: &Build, target: &str) {
// tools and libs on all platforms.
cfg.build();
t!(File::create(&done_stamp));
t!(t!(File::create(&done_stamp)).write_all(stamp_contents.as_bytes()));
}
fn check_llvm_version(build: &Build, llvm_config: &Path) {

View file

@ -40,17 +40,23 @@ pub fn check(build: &mut Build) {
panic!("PATH contains invalid character '\"'");
}
}
let have_cmd = |cmd: &OsStr| {
for path in env::split_paths(&path).map(|p| p.join(cmd)) {
if fs::metadata(&path).is_ok() ||
fs::metadata(path.with_extension("exe")).is_ok() {
return Some(path);
}
}
return None;
};
let mut need_cmd = |cmd: &OsStr| {
if !checked.insert(cmd.to_owned()) {
return
}
for path in env::split_paths(&path).map(|p| p.join(cmd)) {
if fs::metadata(&path).is_ok() ||
fs::metadata(path.with_extension("exe")).is_ok() {
return
}
if have_cmd(cmd).is_none() {
panic!("\n\ncouldn't find required command: {:?}\n\n", cmd);
}
panic!("\n\ncouldn't find required command: {:?}\n\n", cmd);
};
// If we've got a git directory we're gona need git to update
@ -75,8 +81,13 @@ pub fn check(build: &mut Build) {
need_cmd("python".as_ref());
// If a manual nodejs was added to the config,
// of if a nodejs install is detected through config, use it.
// Look for the nodejs command, needed for emscripten testing
if let Some(node) = have_cmd("node".as_ref()) {
build.config.nodejs = Some(node);
} else if let Some(node) = have_cmd("nodejs".as_ref()) {
build.config.nodejs = Some(node);
}
if let Some(ref s) = build.config.nodejs {
need_cmd(s.as_ref());
}
@ -84,6 +95,13 @@ pub fn check(build: &mut Build) {
// We're gonna build some custom C code here and there, host triples
// also build some C++ shims for LLVM so we need a C++ compiler.
for target in build.config.target.iter() {
// On emscripten we don't actually need the C compiler to just
// build the target artifacts, only for testing. For the sake
// of easier bot configuration, just skip detection.
if target.contains("emscripten") {
continue;
}
need_cmd(build.cc(target).as_ref());
if let Some(ar) = build.ar(target) {
need_cmd(ar.as_ref());
@ -93,6 +111,14 @@ pub fn check(build: &mut Build) {
need_cmd(build.cxx(host).as_ref());
}
// The msvc hosts don't use jemalloc, turn it off globally to
// avoid packaging the dummy liballoc_jemalloc on that platform.
for host in build.config.host.iter() {
if host.contains("msvc") {
build.config.use_jemalloc = false;
}
}
// Externally configured LLVM requires FileCheck to exist
let filecheck = build.llvm_filecheck(&build.config.build);
if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests {
@ -100,15 +126,6 @@ pub fn check(build: &mut Build) {
}
for target in build.config.target.iter() {
// Either can't build or don't want to run jemalloc on these targets
if target.contains("rumprun") ||
target.contains("bitrig") ||
target.contains("openbsd") ||
target.contains("msvc") ||
target.contains("emscripten") {
build.config.use_jemalloc = false;
}
// Can't compile for iOS unless we're on OSX
if target.contains("apple-ios") &&
!build.config.build.contains("apple-darwin") {
@ -129,8 +146,8 @@ pub fn check(build: &mut Build) {
}
}
None => {
panic!("when targeting MUSL either the build.musl-root \
option or the target.$TARGET.musl-root one must \
panic!("when targeting MUSL either the rust.musl-root \
option or the target.$TARGET.musl-root option must \
be specified in config.toml")
}
}

View file

@ -140,6 +140,9 @@ macro_rules! targets {
(dist_std, DistStd { compiler: Compiler<'a> }),
(dist_src, DistSrc { _dummy: () }),
// install target
(install, Install { stage: u32 }),
// Misc targets
(android_copy_libs, AndroidCopyLibs { compiler: Compiler<'a> }),
}
@ -171,6 +174,8 @@ targets!(define_source);
/// into a topologically sorted list which when executed left-to-right will
/// correctly sequence the entire build.
pub fn all(build: &Build) -> Vec<Step> {
build.verbose("inferred build steps:");
let mut ret = Vec::new();
let mut all = HashSet::new();
for target in top_level(build) {
@ -184,6 +189,7 @@ pub fn all(build: &Build) -> Vec<Step> {
set: &mut HashSet<Step<'a>>) {
if set.insert(target.clone()) {
for dep in target.deps(build) {
build.verbose(&format!("{:?}\n -> {:?}", target, dep));
fill(build, &dep, ret, set);
}
ret.push(target.clone());
@ -246,8 +252,7 @@ fn top_level(build: &Build) -> Vec<Step> {
}
}
return targets
targets
}
fn add_steps<'a>(build: &'a Build,
@ -415,7 +420,6 @@ impl<'a> Step<'a> {
self.check_crate_std(compiler),
self.check_crate_test(compiler),
self.check_debuginfo(compiler),
self.dist(stage),
];
// If we're testing the build triple, then we know we can
@ -460,9 +464,12 @@ impl<'a> Step<'a> {
// misc
self.check_linkcheck(stage),
self.check_tidy(stage),
// can we make the distributables?
self.dist(stage),
]);
}
return base
base
}
Source::CheckLinkcheck { stage } => {
vec![self.tool_linkchecker(stage), self.doc(stage)]
@ -483,7 +490,6 @@ impl<'a> Step<'a> {
Source::CheckCodegenUnits { compiler } |
Source::CheckIncremental { compiler } |
Source::CheckUi { compiler } |
Source::CheckRustdoc { compiler } |
Source::CheckPretty { compiler } |
Source::CheckCFail { compiler } |
Source::CheckRPassValgrind { compiler } |
@ -506,6 +512,7 @@ impl<'a> Step<'a> {
self.debugger_scripts(compiler.stage),
]
}
Source::CheckRustdoc { compiler } |
Source::CheckRPassFull { compiler } |
Source::CheckRFailFull { compiler } |
Source::CheckCFailFull { compiler } |
@ -517,7 +524,7 @@ impl<'a> Step<'a> {
self.target(compiler.host).tool_compiletest(compiler.stage)]
}
Source::CheckDocs { compiler } => {
vec![self.libstd(compiler)]
vec![self.libtest(compiler)]
}
Source::CheckErrorIndex { compiler } => {
vec![self.libstd(compiler),
@ -585,7 +592,11 @@ impl<'a> Step<'a> {
base.push(target.dist_std(compiler));
}
}
return base
base
}
Source::Install { stage } => {
vec![self.dist(stage)]
}
Source::AndroidCopyLibs { compiler } => {

View file

@ -25,7 +25,9 @@ pub fn run_silent(cmd: &mut Command) {
};
if !status.success() {
fail(&format!("command did not execute successfully: {:?}\n\
expected success, got: {}", cmd, status));
expected success, got: {}",
cmd,
status));
}
}
@ -65,7 +67,9 @@ pub fn output(cmd: &mut Command) -> String {
};
if !output.status.success() {
panic!("command did not execute successfully: {:?}\n\
expected success, got: {}", cmd, output.status);
expected success, got: {}",
cmd,
output.status);
}
String::from_utf8(output.stdout).unwrap()
}

@ -1 +1 @@
Subproject commit 8598065bd965d9713bfafb6c1e766d63a7b17b89
Subproject commit f03ba5a4e8bf16dcf42dd742a4ce255c36321356

View file

@ -4,7 +4,7 @@ Concurrency and parallelism are incredibly important topics in computer
science, and are also a hot topic in industry today. Computers are gaining more
and more cores, yet many programmers aren't prepared to fully utilize them.
Rust's memory safety features also apply to its concurrency story too. Even
Rust's memory safety features also apply to its concurrency story. Even
concurrent Rust programs must be memory safe, having no data races. Rust's type
system is up to the task, and gives you powerful ways to reason about
concurrent code at compile time.
@ -281,8 +281,8 @@ And... still gives us an error.
```
`Arc<T>` by default has immutable contents. It allows the _sharing_ of data
between threads, but shared mutable data is unsafe and when threads are
involved can cause data races!
between threads, but shared mutable data is unsafeand when threads are
involvedcan cause data races!
Usually when we wish to make something in an immutable position mutable, we use

View file

@ -1,4 +1,4 @@
% `const` and `static`
% const and static
Rust has a way of defining constants with the `const` keyword:

View file

@ -69,7 +69,7 @@ foo(&counted);
All weve done is wrap our `String` in an `Rc<T>`. But we can now pass the
`Rc<String>` around anywhere wed have a `String`. The signature of `foo`
didnt change, but works just as well with either type. This example has two
conversions: `Rc<String>` to `String` and then `String` to `&str`. Rust will do
conversions: `&Rc<String>` to `&String` and then `&String` to `&str`. Rust will do
this as many times as possible until the types match.
Another very common implementation provided by the standard library is:

View file

@ -166,12 +166,22 @@ you can find the Rust executables in a directory like
`"C:\Program Files\Rust stable GNU 1.x\bin"`.
Rust does not do its own linking, and so youll need to have a linker
installed. Doing so will depend on your specific system, consult its
documentation for more details.
installed. Doing so will depend on your specific system. For
Linux-based systems, Rust will attempt to call `cc` for linking. On
`windows-msvc` (Rust built on Windows with Microsoft Visual Studio),
this depends on having [Microsoft Visual C++ Build Tools][msvbt]
installed. These do not need to be in `%PATH%` as `rustc` will find
them automatically. In general, if you have your linker in a
non-traditional location you can call `rustc
linker=/path/to/cc`, where `/path/to/cc` should point to your linker path.
If not, there are a number of places where we can get help. The easiest is
[the #rust-beginners IRC channel on irc.mozilla.org][irc-beginners] and for
general discussion [the #rust IRC channel on irc.mozilla.org][irc], which we
[msvbt]: http://landinghub.visualstudio.com/visual-cpp-build-tools
If you are still stuck, there are a number of places where we can get
help. The easiest is
[the #rust-beginners IRC channel on irc.mozilla.org][irc-beginners]
and for general discussion
[the #rust IRC channel on irc.mozilla.org][irc], which we
can access through [Mibbit][mibbit]. Then we'll be chatting with other
Rustaceans (a silly nickname we call ourselves) who can help us out. Other great
resources include [the users forum][users] and [Stack Overflow][stackoverflow].
@ -230,12 +240,13 @@ $ cd hello_world
## Writing and Running a Rust Program
Next, make a new source file and call it *main.rs*. Rust files always end
in a *.rs* extension. If youre using more than one word in your filename, use
an underscore to separate them; for example, you'd use *hello_world.rs* rather
than *helloworld.rs*.
We need to create a source file for our Rust program. Rust files always end
in a *.rs* extension. If you are using more than one word in your filename,
use an underscore to separate them; for example, you would use
*my_program.rs* rather than *myprogram.rs*.
Now open the *main.rs* file you just created, and type the following code:
Now, make a new file and call it *main.rs*. Open the file and type
the following code:
```rust
fn main() {
@ -494,6 +505,9 @@ $ cargo run
Hello, world!
```
The `run` command comes in handy when you need to rapidly iterate on a
project.
Notice that this example didnt re-build the project. Cargo figured out that
the file hasnt changed, and so it just ran the binary. If you'd modified your
source code, Cargo would have rebuilt the project before running it, and you

View file

@ -56,9 +56,7 @@ $ cargo build
Excellent! Open up your `src/main.rs` again. Well be writing all of
our code in this file.
Before we move on, let me show you one more Cargo command: `run`. `cargo run`
is kind of like `cargo build`, but it also then runs the produced executable.
Try it out:
Remember the `run` command from last chapter? Try it out again here:
```bash
$ cargo run
@ -67,9 +65,8 @@ $ cargo run
Hello, world!
```
Great! The `run` command comes in handy when you need to rapidly iterate on a
project. Our game is such a project, we need to quickly test each
iteration before moving on to the next one.
Great! Our game is just the kind of project `run` is good for: we need
to quickly test each iteration before moving on to the next one.
# Processing a Guess
@ -279,7 +276,7 @@ displaying the message.
[expect]: ../std/result/enum.Result.html#method.expect
[panic]: error-handling.html
If we leave off calling this method, our program will compile, but
If we do not call `expect()`, our program will compile, but
well get a warning:
```bash

View file

@ -50,29 +50,94 @@ complicated. For example, imagine this set of operations:
4. You decide to use the resource.
Uh oh! Your reference is pointing to an invalid resource. This is called a
dangling pointer or use after free, when the resource is memory.
dangling pointer or use after free, when the resource is memory. A small
example of such a situation would be:
```rust,compile_fail
let r; // Introduce reference: r
{
let i = 1; // Introduce scoped value: i
r = &i; // Store reference of i in r
} // i goes out of scope and is dropped.
println!("{}", r); // r still refers to i
```
To fix this, we have to make sure that step four never happens after step
three. The ownership system in Rust does this through a concept called
lifetimes, which describe the scope that a reference is valid for.
three. In the small example above the Rust compiler is able to report the issue
as it can see the lifetimes of the various values in the function.
When we have a function that takes an argument by reference, we can be
implicit or explicit about the lifetime of the reference:
When we have a function that takes arguments by reference the situation becomes
more complex. Consider the following example:
```rust
// implicit
fn foo(x: &i32) {
```rust,compile_fail,E0106
fn skip_prefix(line: &str, prefix: &str) -> &str {
// ...
# line
}
// explicit
fn bar<'a>(x: &'a i32) {
let line = "lang:en=Hello World!";
let lang = "en";
let v;
{
let p = format!("lang:{}=", lang); // -+ p goes into scope
v = skip_prefix(line, p.as_str()); // |
} // -+ p goes out of scope
println!("{}", v);
```
Here we have a function `skip_prefix` which takes two `&str` references
as parameters and returns a single `&str` reference. We call it
by passing in references to `line` and `p`: Two variables with different
lifetimes. Now the safety of the `println!`-line depends on whether the
reference returned by `skip_prefix` function references the still living
`line` or the already dropped `p` string.
Because of the above ambiguity, Rust will refuse to compile the example
code. To get it to compile we need to tell the compiler more about the
lifetimes of the references. This can be done by making the lifetimes
explicit in the function declaration:
```rust
fn skip_prefix<'a, 'b>(line: &'a str, prefix: &'b str) -> &'a str {
// ...
# line
}
```
Let's examine the changes without going too deep into the syntax for now -
we'll get to that later. The first change was adding the `<'a, 'b>` after the
method name. This introduces two lifetime parameters: `'a` and `'b`. Next each
reference in the function signature was associated with one of the lifetime
parameters by adding the lifetime name after the `&`. This tells the compiler
how the lifetimes between different references are related.
As a result the compiler is now able to deduce that the return value of
`skip_prefix` has the same lifetime as the `line` parameter, which makes the `v`
reference safe to use even after the `p` goes out of scope in the original
example.
In addition to the compiler being able to validate the usage of `skip_prefix`
return value, it can also ensure that the implementation follows the contract
established by the function declaration. This is useful especially when you are
implementing traits that are introduced [later in the book][traits].
**Note** It's important to understand that lifetime annotations are
_descriptive_, not _prescriptive_. This means that how long a reference is valid
is determined by the code, not by the annotations. The annotations, however,
give information about lifetimes to the compiler that uses them to check the
validity of references. The compiler can do so without annotations in simple
cases, but needs the programmers support in complex scenarios.
[traits]: traits.html
# Syntax
The `'a` reads the lifetime a. Technically, every reference has some lifetime
associated with it, but the compiler lets you elide (i.e. omit, see
["Lifetime Elision"][lifetime-elision] below) them in common cases.
Before we get to that, though, lets break the explicit example down:
["Lifetime Elision"][lifetime-elision] below) them in common cases. Before we
get to that, though, lets look at a short example with explicit lifetimes:
[lifetime-elision]: #lifetime-elision
@ -90,7 +155,8 @@ focus on the lifetimes aspect.
[generics]: generics.html
We use `<>` to declare our lifetimes. This says that `bar` has one lifetime,
`'a`. If we had two reference parameters, it would look like this:
`'a`. If we had two reference parameters with different lifetimes, it would
look like this:
```rust,ignore

View file

@ -57,13 +57,13 @@ of scope at the end of `foo()`, Rust will clean up everything related to the
vector, even the heap-allocated memory. This happens deterministically, at the
end of the scope.
We'll cover [vectors] in detail later in this chapter; we only use them
We covered [vectors] in the previous chapter; we use them
here as an example of a type that allocates space on the heap at runtime. They
behave like [arrays], except their size may change by `push()`ing more
elements onto them.
Vectors have a [generic type][generics] `Vec<T>`, so in this example `v` will have type
`Vec<i32>`. We'll cover generics in detail later in this chapter.
`Vec<i32>`. We'll cover [generics] in detail in a later chapter.
[arrays]: primitive-types.html#arrays
[vectors]: vectors.html

View file

@ -86,7 +86,7 @@ fn main() {
return v.iter().fold(0, |a, &b| a + b);
}
// Borrow two vectors and sum them.
// This kind of borrowing does not allow mutation to the borrowed.
// This kind of borrowing does not allow mutation through the borrowed reference.
fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 {
// do stuff with v1 and v2
let s1 = sum_vec(v1);
@ -240,7 +240,7 @@ fn main() {
In other words, the mutable borrow is held through the rest of our example. What
we want is for the mutable borrow by `y` to end so that the resource can be
returned to the owner, `x`. `x` can then provide a immutable borrow to `println!`.
returned to the owner, `x`. `x` can then provide an immutable borrow to `println!`.
In Rust, borrowing is tied to the scope that the borrow is valid for. And our
scopes look like this:

View file

@ -61,7 +61,6 @@
* `-` (`- expr`): arithmetic negation. Overloadable (`Neg`).
* `-=` (`var -= expr`): arithmetic subtraction & assignment. Overloadable (`SubAssign`).
* `->` (`fn(…) -> type`, `|…| -> type`): function and closure return type. See [Functions], [Closures].
* `-> !` (`fn(…) -> !`, `|…| -> !`): diverging function or closure. See [Diverging Functions].
* `.` (`expr.ident`): member access. See [Structs], [Method Syntax].
* `..` (`..`, `expr..`, `..expr`, `expr..expr`): right-exclusive range literal.
* `..` (`..expr`): struct literal update syntax. See [Structs (Update syntax)].
@ -159,6 +158,10 @@
* `/*!…*/`: inner block doc comment. See [Comments].
* `/**…*/`: outer block doc comment. See [Comments].
<!-- Special types -->
* `!`: always empty Never type. See [Diverging Functions].
<!-- Various things involving parens and tuples -->
* `()`: empty tuple (*a.k.a.* unit), both literal and type.

View file

@ -380,9 +380,9 @@ the `tests` directory.
# The `tests` directory
Each file in `tests/*.rs` directory is treated as individual crate.
So, to write an integration test, let's make a `tests` directory, and
put a `tests/integration_test.rs` file inside, with this as its contents:
Each file in `tests/*.rs` directory is treated as an individual crate.
To write an integration test, let's make a `tests` directory and
put a `tests/integration_test.rs` file inside with this as its contents:
```rust,ignore
extern crate adder;

View file

@ -291,7 +291,7 @@ let result = f.write(buf);
We need to `use` the `Write` trait first:
```rust,ignore
```rust,no_run
use std::io::Write;
let mut f = std::fs::File::create("foo.txt").expect("Couldnt create foo.txt");

View file

@ -1,4 +1,4 @@
% `type` Aliases
% Type Aliases
The `type` keyword lets you declare an alias of another type:

View file

@ -161,7 +161,7 @@ Could not compile `hello_world`.
Rust will not let us use a value that has not been initialized.
Let take a minute to talk about this stuff we've added to `println!`.
Let us take a minute to talk about this stuff we've added to `println!`.
If you include two curly braces (`{}`, some call them moustaches...) in your
string to print, Rust will interpret this as a request to interpolate some sort

View file

@ -5,4 +5,3 @@ or the <a href="https://opensource.org/licenses/MIT">MIT license</a>, at your op
</p><p>
This file may not be copied, modified, or distributed except according to those terms.
</p></footer>
<script type="text/javascript" src="playpen.js"></script>

View file

@ -764,6 +764,13 @@ bound-list := bound | bound '+' bound-list
bound := path | lifetime
```
### Never type
An empty type
```antlr
never_type : "!" ;
```
### Object types
**FIXME:** grammar?

View file

@ -2472,8 +2472,7 @@ The currently implemented features of the reference compiler are:
* - `default_type_parameter_fallback` - Allows type parameter defaults to
influence type inference.
* - `stmt_expr_attributes` - Allows attributes on expressions and
non-item statements.
* - `stmt_expr_attributes` - Allows attributes on expressions.
* - `type_ascription` - Allows type ascription expressions `expr: Type`.
@ -3110,10 +3109,12 @@ the lambda expression captures its environment by reference, effectively
borrowing pointers to all outer variables mentioned inside the function.
Alternately, the compiler may infer that a lambda expression should copy or
move values (depending on their type) from the environment into the lambda
expression's captured environment.
expression's captured environment. A lambda can be forced to capture its
environment by moving values by prefixing it with the `move` keyword.
In this example, we define a function `ten_times` that takes a higher-order
function argument, and we then call it with a lambda expression as an argument:
function argument, and we then call it with a lambda expression as an argument,
followed by a lambda expression that moves values from its environment.
```
fn ten_times<F>(f: F) where F: Fn(i32) {
@ -3123,6 +3124,9 @@ fn ten_times<F>(f: F) where F: Fn(i32) {
}
ten_times(|j| println!("hello, {}", j));
let word = "konnichiwa".to_owned();
ten_times(move |j| println!("{}, {}", word, j));
```
### Infinite loops
@ -3959,6 +3963,16 @@ the top-level type for the implementation of the called method. If no such metho
found, `.deref()` is called and the compiler continues to search for the method
implementation in the returned type `U`.
## The `Send` trait
The `Send` trait indicates that a value of this type is safe to send from one
thread to another.
## The `Sync` trait
The `Sync` trait indicates that a value of this type is safe to share between
multiple threads.
# Memory model
A Rust program's memory consists of a static set of *items* and a *heap*.
@ -4009,9 +4023,9 @@ Methods that take either `self` or `Box<Self>` can optionally place them in a
mutable variable by prefixing them with `mut` (similar to regular arguments):
```
trait Changer {
fn change(mut self) -> Self;
fn modify(mut self: Box<Self>) -> Box<Self>;
trait Changer: Sized {
fn change(mut self) {}
fn modify(mut self: Box<Self>) {}
}
```
@ -4064,6 +4078,12 @@ be ignored in favor of only building the artifacts specified by command line.
Rust code into an existing non-Rust application because it will not have
dynamic dependencies on other Rust code.
* `--crate-type=cdylib`, `#[crate_type = "cdylib"]` - A dynamic system
library will be produced. This is used when compiling Rust code as
a dynamic library to be loaded from another language. This output type will
create `*.so` files on Linux, `*.dylib` files on OSX, and `*.dll` files on
Windows.
* `--crate-type=rlib`, `#[crate_type = "rlib"]` - A "Rust library" file will be
produced. This is used as an intermediate artifact and can be thought of as a
"static Rust library". These `rlib` files, unlike `staticlib` files, are

View file

@ -159,7 +159,7 @@ em {
footer {
border-top: 1px solid #ddd;
font-size: 14.3px;
font-size: 14px;
font-style: italic;
padding-top: 5px;
margin-top: 3em;
@ -336,13 +336,11 @@ table th {
/* Code snippets */
.rusttest { display: none; }
pre.rust { position: relative; }
a.test-arrow {
background-color: rgba(78, 139, 202, 0.2);
display: inline-block;
position: absolute;
background-color: #4e8bca;
color: #f5f5f5;
padding: 5px 10px 5px 10px;
border-radius: 5px;
@ -350,6 +348,10 @@ a.test-arrow {
top: 5px;
right: 5px;
}
a.test-arrow:hover{
background-color: #4e8bca;
text-decoration: none;
}
.unstable-feature {
border: 2px solid red;

View file

@ -328,7 +328,7 @@ def extract_length_and_ptr_from_slice(slice_val):
UNQUALIFIED_TYPE_MARKERS = frozenset(["(", "[", "&", "*"])
def extract_type_name(qualified_type_name):
'''Extracts the type name from a fully qualified path'''
"""Extracts the type name from a fully qualified path"""
if qualified_type_name[0] in UNQUALIFIED_TYPE_MARKERS:
return qualified_type_name

View file

@ -170,7 +170,7 @@ def rust_pretty_printer_lookup_function(gdb_val):
#=------------------------------------------------------------------------------
# Pretty Printer Classes
#=------------------------------------------------------------------------------
class RustStructPrinter:
class RustStructPrinter(object):
def __init__(self, val, omit_first_field, omit_type_name, is_tuple_like):
self.__val = val
self.__omit_first_field = omit_first_field
@ -205,11 +205,12 @@ class RustStructPrinter:
return ""
class RustSlicePrinter:
class RustSlicePrinter(object):
def __init__(self, val):
self.__val = val
def display_hint(self):
@staticmethod
def display_hint():
return "array"
def to_string(self):
@ -226,7 +227,7 @@ class RustSlicePrinter:
yield (str(index), (raw_ptr + index).dereference())
class RustStringSlicePrinter:
class RustStringSlicePrinter(object):
def __init__(self, val):
self.__val = val
@ -236,11 +237,12 @@ class RustStringSlicePrinter:
return '"%s"' % raw_ptr.string(encoding="utf-8", length=length)
class RustStdVecPrinter:
class RustStdVecPrinter(object):
def __init__(self, val):
self.__val = val
def display_hint(self):
@staticmethod
def display_hint():
return "array"
def to_string(self):
@ -255,7 +257,7 @@ class RustStdVecPrinter:
yield (str(index), (gdb_ptr + index).dereference())
class RustStdStringPrinter:
class RustStdStringPrinter(object):
def __init__(self, val):
self.__val = val
@ -266,7 +268,7 @@ class RustStdStringPrinter:
length=length)
class RustCStyleVariantPrinter:
class RustCStyleVariantPrinter(object):
def __init__(self, val):
assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_ENUM
self.__val = val
@ -275,7 +277,7 @@ class RustCStyleVariantPrinter:
return str(self.__val.get_wrapped_value())
class IdentityPrinter:
class IdentityPrinter(object):
def __init__(self, string):
self.string = string

View file

@ -37,14 +37,14 @@ DEBUG_OUTPUT = False
def print_debug(s):
"Print something if DEBUG_OUTPUT is True"
"""Print something if DEBUG_OUTPUT is True"""
global DEBUG_OUTPUT
if DEBUG_OUTPUT:
print("DEBUG: " + str(s))
def normalize_whitespace(s):
"Replace newlines, tabs, multiple spaces, etc with exactly one space"
"""Replace newlines, tabs, multiple spaces, etc with exactly one space"""
return re.sub("\s+", " ", s)
@ -71,7 +71,7 @@ registered_breakpoints = set()
def execute_command(command_interpreter, command):
"Executes a single CLI command"
"""Executes a single CLI command"""
global new_breakpoints
global registered_breakpoints

View file

@ -171,10 +171,10 @@ def print_val(lldb_val, internal_dict):
#=--------------------------------------------------------------------------------------------------
def print_struct_val(val, internal_dict, omit_first_field, omit_type_name, is_tuple_like):
'''
"""
Prints a struct, tuple, or tuple struct value with Rust syntax.
Ignores any fields before field_start_index.
'''
"""
assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_STRUCT
if omit_type_name:
@ -221,7 +221,7 @@ def print_struct_val(val, internal_dict, omit_first_field, omit_type_name, is_tu
"body": body}
def print_pointer_val(val, internal_dict):
'''Prints a pointer value with Rust syntax'''
"""Prints a pointer value with Rust syntax"""
assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_PTR
sigil = "&"
type_name = val.type.get_unqualified_type_name()
@ -275,8 +275,8 @@ def print_std_string_val(val, internal_dict):
#=--------------------------------------------------------------------------------------------------
def print_array_of_values(array_name, data_ptr_val, length, internal_dict):
'''Prints a contigous memory range, interpreting it as values of the
pointee-type of data_ptr_val.'''
"""Prints a contigous memory range, interpreting it as values of the
pointee-type of data_ptr_val."""
data_ptr_type = data_ptr_val.type
assert data_ptr_type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_PTR

View file

@ -18,7 +18,7 @@ LIB_PREFIX=lib
OS=`uname -s`
case $OS in
("Linux"|"FreeBSD"|"DragonFly"|"Bitrig"|"OpenBSD"|"SunOS")
("Linux"|"FreeBSD"|"DragonFly"|"Bitrig"|"OpenBSD"|"SunOS"|"Haiku")
BIN_SUF=
LIB_SUF=.so
;;
@ -71,6 +71,7 @@ cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}log*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}rbml*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}serialize*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}term*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}proc_macro*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
# do not fail if one of the above fails, as all we need is a working rustc!
exit 0

View file

@ -119,16 +119,19 @@ class Void(Type):
def __init__(self):
Type.__init__(self, 0)
def compiler_ctor(self):
@staticmethod
def compiler_ctor():
return '::VOID'
def compiler_ctor_ref(self):
return '&' + self.compiler_ctor()
def rust_name(self):
@staticmethod
def rust_name():
return '()'
def type_info(self, platform_info):
@staticmethod
def type_info(platform_info):
return None
def __eq__(self, other):
@ -282,7 +285,7 @@ class Vector(Type):
class Pointer(Type):
def __init__(self, elem, llvm_elem, const):
self._elem = elem;
self._elem = elem
self._llvm_elem = llvm_elem
self._const = const
Type.__init__(self, BITWIDTH_POINTER)
@ -503,7 +506,7 @@ class GenericIntrinsic(object):
# must be a power of two
assert width & (width - 1) == 0
def recur(processed, untouched):
if untouched == []:
if not untouched:
ret = processed[0]
args = processed[1:]
yield MonomorphicIntrinsic(self._platform, self.intrinsic, width,
@ -756,22 +759,26 @@ class ExternBlock(object):
def __init__(self):
pass
def open(self, platform):
@staticmethod
def open(platform):
return 'extern "platform-intrinsic" {'
def render(self, mono):
@staticmethod
def render(mono):
return ' fn {}{}{};'.format(mono.platform_prefix(),
mono.intrinsic_name(),
mono.intrinsic_signature())
def close(self):
@staticmethod
def close():
return '}'
class CompilerDefs(object):
def __init__(self):
pass
def open(self, platform):
@staticmethod
def open(platform):
return '''\
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
@ -798,7 +805,8 @@ pub fn find(name: &str) -> Option<Intrinsic> {{
if !name.starts_with("{0}") {{ return None }}
Some(match &name["{0}".len()..] {{'''.format(platform.platform_prefix())
def render(self, mono):
@staticmethod
def render(mono):
return '''\
"{}" => Intrinsic {{
inputs: {{ static INPUTS: [&'static Type; {}] = [{}]; &INPUTS }},
@ -810,7 +818,8 @@ pub fn find(name: &str) -> Option<Intrinsic> {{
mono.compiler_ret(),
mono.llvm_name())
def close(self):
@staticmethod
def close():
return '''\
_ => return None,
})

View file

@ -177,7 +177,6 @@ def run(test):
def interact(proc, queue):
line = ""
n = 0
while proc.poll() is None:
line = proc.stdout.readline()
@ -185,7 +184,6 @@ def interact(proc, queue):
continue
assert line.endswith('\n'), "incomplete line: " + repr(line)
queue.put(line)
line = ""
n += 1
if n % UPDATE_EVERY_N == 0:
msg("got", str(n // 1000) + "k", "records")

View file

@ -82,28 +82,28 @@ def load_unicode_data(f):
canon_decomp = {}
compat_decomp = {}
udict = {};
range_start = -1;
udict = {}
range_start = -1
for line in fileinput.input(f):
data = line.split(';');
data = line.split(';')
if len(data) != 15:
continue
cp = int(data[0], 16);
cp = int(data[0], 16)
if is_surrogate(cp):
continue
if range_start >= 0:
for i in xrange(range_start, cp):
udict[i] = data;
range_start = -1;
udict[i] = data
range_start = -1
if data[1].endswith(", First>"):
range_start = cp;
continue;
udict[cp] = data;
range_start = cp
continue
udict[cp] = data
for code in udict:
[code_org, name, gencat, combine, bidi,
(code_org, name, gencat, combine, bidi,
decomp, deci, digit, num, mirror,
old, iso, upcase, lowcase, titlecase ] = udict[code];
old, iso, upcase, lowcase, titlecase) = udict[code]
# generate char to char direct common and simple conversions
# uppercase to lowercase
@ -382,7 +382,7 @@ def emit_bool_trie(f, name, t_data, is_pub=True):
global bytes_old, bytes_new
bytes_old += 8 * len(t_data)
CHUNK = 64
rawdata = [False] * 0x110000;
rawdata = [False] * 0x110000
for (lo, hi) in t_data:
for cp in range(lo, hi + 1):
rawdata[cp] = True

View file

@ -10,35 +10,11 @@
#![stable(feature = "rust1", since = "1.0.0")]
//! Threadsafe reference-counted boxes (the `Arc<T>` type).
//! Thread-safe reference-counting pointers.
//!
//! The `Arc<T>` type provides shared ownership of an immutable value through
//! atomic reference counting.
//! See the [`Arc<T>`][arc] documentation for more details.
//!
//! `Weak<T>` is a weak reference to the `Arc<T>` box, and it is created by
//! the `downgrade` method.
//! # Examples
//!
//! Sharing some immutable data between threads:
//!
// Note that we **do not** run these tests here. The windows builders get super
// unhappy of a thread outlives the main thread and then exits at the same time
// (something deadlocks) so we just avoid this entirely by not running these
// tests.
//! ```no_run
//! use std::sync::Arc;
//! use std::thread;
//!
//! let five = Arc::new(5);
//!
//! for _ in 0..10 {
//! let five = five.clone();
//!
//! thread::spawn(move || {
//! println!("{:?}", five);
//! });
//! }
//! ```
//! [arc]: struct.Arc.html
use boxed::Box;
@ -62,72 +38,114 @@ use heap::deallocate;
const MAX_REFCOUNT: usize = (isize::MAX) as usize;
/// An atomically reference counted wrapper for shared state.
/// Destruction is deterministic, and will occur as soon as the last owner is
/// gone. It is marked as `Send` because it uses atomic reference counting.
/// A thread-safe reference-counting pointer.
///
/// If you do not need thread-safety, and just need shared ownership, consider
/// the [`Rc<T>` type](../rc/struct.Rc.html). It is the same as `Arc<T>`, but
/// does not use atomics, making it both thread-unsafe as well as significantly
/// faster when updating the reference count.
/// The type `Arc<T>` provides shared ownership of a value of type `T`,
/// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces
/// a new pointer to the same value in the heap. When the last `Arc`
/// pointer to a given value is destroyed, the pointed-to value is
/// also destroyed.
///
/// Note: the inherent methods defined on `Arc<T>` are all associated functions,
/// which means that you have to call them as e.g. `Arc::get_mut(&value)`
/// instead of `value.get_mut()`. This is so that there are no conflicts with
/// methods on the inner type `T`, which are what you want to call in the
/// majority of cases.
/// Shared references in Rust disallow mutation by default, and `Arc` is no
/// exception. If you need to mutate through an `Arc`, use [`Mutex`][mutex],
/// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types.
///
/// # Examples
/// `Arc` uses atomic operations for reference counting, so `Arc`s can be
/// sent between threads. In other words, `Arc<T>` implements [`Send`][send]
/// as long as `T` implements `Send` and [`Sync`][sync]. The disadvantage is
/// that atomic operations are more expensive than ordinary memory accesses.
/// If you are not sharing reference-counted values between threads, consider
/// using [`rc::Rc`][rc] for lower overhead. `Rc` is a safe default, because
/// the compiler will catch any attempt to send an `Rc` between threads.
/// However, a library might choose `Arc` in order to give library consumers
/// more flexibility.
///
/// In this example, a large vector of data will be shared by several threads. First we
/// wrap it with a `Arc::new` and then clone the `Arc<T>` reference for every thread (which will
/// increase the reference count atomically).
/// The [`downgrade`][downgrade] method can be used to create a non-owning
/// [`Weak`][weak] pointer. A `Weak` pointer can be [`upgrade`][upgrade]d
/// to an `Arc`, but this will return [`None`][option] if the value has
/// already been dropped.
///
/// A cycle between `Arc` pointers will never be deallocated. For this reason,
/// `Weak` is used to break cycles. For example, a tree could have strong
/// `Arc` pointers from parent nodes to children, and `Weak` pointers from
/// children back to their parents.
///
/// `Arc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait),
/// so you can call `T`'s methods on a value of type `Arc<T>`. To avoid name
/// clashes with `T`'s methods, the methods of `Arc<T>` itself are [associated
/// functions][assoc], called using function-like syntax:
///
/// ```
/// use std::sync::Arc;
/// use std::thread;
/// let my_arc = Arc::new(());
///
/// fn main() {
/// let numbers: Vec<_> = (0..100).collect();
/// let shared_numbers = Arc::new(numbers);
///
/// for _ in 0..10 {
/// // prepare a copy of reference here and it will be moved to the thread
/// let child_numbers = shared_numbers.clone();
///
/// thread::spawn(move || {
/// let local_numbers = &child_numbers[..];
///
/// // Work with the local numbers
/// });
/// }
/// }
/// Arc::downgrade(&my_arc);
/// ```
/// You can also share mutable data between threads safely
/// by putting it inside `Mutex` and then share `Mutex` immutably
/// with `Arc<T>` as shown below.
///
// See comment at the top of this file for why the test is no_run
/// `Weak<T>` does not auto-dereference to `T`, because the value may have
/// already been destroyed.
///
/// [arc]: struct.Arc.html
/// [weak]: struct.Weak.html
/// [rc]: ../../std/rc/struct.Rc.html
/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
/// [mutex]: ../../std/sync/struct.Mutex.html
/// [rwlock]: ../../std/sync/struct.RwLock.html
/// [atomic]: ../../std/sync/atomic/index.html
/// [send]: ../../std/marker/trait.Send.html
/// [sync]: ../../std/marker/trait.Sync.html
/// [deref]: ../../std/ops/trait.Deref.html
/// [downgrade]: struct.Arc.html#method.downgrade
/// [upgrade]: struct.Weak.html#method.upgrade
/// [option]: ../../std/option/enum.Option.html
/// [assoc]: ../../book/method-syntax.html#associated-functions
///
/// # Examples
///
/// Sharing some immutable data between threads:
///
// Note that we **do not** run these tests here. The windows builders get super
// unhappy if a thread outlives the main thread and then exits at the same time
// (something deadlocks) so we just avoid this entirely by not running these
// tests.
/// ```no_run
/// use std::sync::{Arc, Mutex};
/// use std::sync::Arc;
/// use std::thread;
///
/// let five = Arc::new(Mutex::new(5));
/// let five = Arc::new(5);
///
/// for _ in 0..10 {
/// let five = five.clone();
///
/// thread::spawn(move || {
/// let mut number = five.lock().unwrap();
///
/// *number += 1;
///
/// println!("{}", *number); // prints 6
/// println!("{:?}", five);
/// });
/// }
/// ```
#[cfg_attr(stage0, unsafe_no_drop_flag)]
///
/// Sharing a mutable `AtomicUsize`:
///
/// ```no_run
/// use std::sync::Arc;
/// use std::sync::atomic::{AtomicUsize, Ordering};
/// use std::thread;
///
/// let val = Arc::new(AtomicUsize::new(5));
///
/// for _ in 0..10 {
/// let val = val.clone();
///
/// thread::spawn(move || {
/// let v = val.fetch_add(1, Ordering::SeqCst);
/// println!("{:?}", v);
/// });
/// }
/// ```
///
/// See the [`rc` documentation][rc_examples] for more examples of reference
/// counting in general.
///
/// [rc_examples]: ../../std/rc/index.html#examples
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Arc<T: ?Sized> {
ptr: Shared<ArcInner<T>>,
@ -141,19 +159,18 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
#[unstable(feature = "coerce_unsized", issue = "27732")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
/// A weak pointer to an `Arc`.
/// A weak version of [`Arc`][arc].
///
/// Weak pointers will not keep the data inside of the `Arc` alive, and can be
/// used to break cycles between `Arc` pointers.
/// `Weak` pointers do not count towards determining if the inner value
/// should be dropped.
///
/// A `Weak<T>` pointer can be upgraded to an `Arc<T>` pointer, but
/// will return `None` if the value has already been dropped.
/// The typical way to obtain a `Weak` pointer is to call
/// [`Arc::downgrade`][downgrade].
///
/// For example, a tree with parent pointers can be represented by putting the
/// nodes behind strong `Arc<T>` pointers, and then storing the parent pointers
/// as `Weak<T>` pointers.
#[cfg_attr(stage0, unsafe_no_drop_flag)]
/// See the [`Arc`][arc] documentation for more details.
///
/// [arc]: struct.Arc.html
/// [downgrade]: struct.Arc.html#method.downgrade
#[stable(feature = "arc_weak", since = "1.4.0")]
pub struct Weak<T: ?Sized> {
ptr: Shared<ArcInner<T>>,
@ -211,12 +228,15 @@ impl<T> Arc<T> {
Arc { ptr: unsafe { Shared::new(Box::into_raw(x)) } }
}
/// Unwraps the contained value if the `Arc<T>` has exactly one strong reference.
/// Returns the contained value, if the `Arc` has exactly one strong reference.
///
/// Otherwise, an `Err` is returned with the same `Arc<T>`.
/// Otherwise, an [`Err`][result] is returned with the same `Arc` that was
/// passed in.
///
/// This will succeed even if there are outstanding weak references.
///
/// [result]: ../../std/result/enum.Result.html
///
/// # Examples
///
/// ```
@ -227,7 +247,7 @@ impl<T> Arc<T> {
///
/// let x = Arc::new(4);
/// let _y = x.clone();
/// assert_eq!(Arc::try_unwrap(x), Err(Arc::new(4)));
/// assert_eq!(*Arc::try_unwrap(x).unwrap_err(), 4);
/// ```
#[inline]
#[stable(feature = "arc_unique", since = "1.4.0")]
@ -253,7 +273,9 @@ impl<T> Arc<T> {
}
impl<T: ?Sized> Arc<T> {
/// Downgrades the `Arc<T>` to a `Weak<T>` reference.
/// Creates a new [`Weak`][weak] pointer to this value.
///
/// [weak]: struct.Weak.html
///
/// # Examples
///
@ -291,7 +313,27 @@ impl<T: ?Sized> Arc<T> {
}
}
/// Get the number of weak references to this value.
/// Gets the number of [`Weak`][weak] pointers to this value.
///
/// Be careful how you use this information, because another thread
/// may change the weak count at any time.
///
/// [weak]: struct.Weak.html
///
/// # Examples
///
/// ```
/// #![feature(arc_counts)]
///
/// use std::sync::Arc;
///
/// let five = Arc::new(5);
/// let _weak_five = Arc::downgrade(&five);
///
/// // This assertion is deterministic because we haven't shared
/// // the `Arc` or `Weak` between threads.
/// assert_eq!(1, Arc::weak_count(&five));
/// ```
#[inline]
#[unstable(feature = "arc_counts", reason = "not clearly useful, and racy",
issue = "28356")]
@ -299,7 +341,25 @@ impl<T: ?Sized> Arc<T> {
this.inner().weak.load(SeqCst) - 1
}
/// Get the number of strong references to this value.
/// Gets the number of strong (`Arc`) pointers to this value.
///
/// Be careful how you use this information, because another thread
/// may change the strong count at any time.
///
/// # Examples
///
/// ```
/// #![feature(arc_counts)]
///
/// use std::sync::Arc;
///
/// let five = Arc::new(5);
/// let _also_five = five.clone();
///
/// // This assertion is deterministic because we haven't shared
/// // the `Arc` between threads.
/// assert_eq!(2, Arc::strong_count(&five));
/// ```
#[inline]
#[unstable(feature = "arc_counts", reason = "not clearly useful, and racy",
issue = "28356")]
@ -336,8 +396,8 @@ impl<T: ?Sized> Arc<T> {
#[unstable(feature = "ptr_eq",
reason = "newly added",
issue = "36497")]
/// Return whether two `Arc` references point to the same value
/// (not just values that compare equal).
/// Returns true if the two `Arc`s point to the same value (not
/// just values that compare as equal).
///
/// # Examples
///
@ -362,9 +422,10 @@ impl<T: ?Sized> Arc<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Clone for Arc<T> {
/// Makes a clone of the `Arc<T>`.
/// Makes a clone of the `Arc` pointer.
///
/// This increases the strong reference count.
/// This creates another pointer to the same inner value, increasing the
/// strong reference count.
///
/// # Examples
///
@ -420,11 +481,17 @@ impl<T: ?Sized> Deref for Arc<T> {
}
impl<T: Clone> Arc<T> {
/// Make a mutable reference into the given `Arc<T>`.
/// If the `Arc<T>` has more than one strong reference, or any weak
/// references, the inner data is cloned.
/// Makes a mutable reference into the given `Arc`.
///
/// This is also referred to as a copy-on-write.
/// If there are other `Arc` or [`Weak`][weak] pointers to the same value,
/// then `make_mut` will invoke [`clone`][clone] on the inner value to
/// ensure unique ownership. This is also referred to as clone-on-write.
///
/// See also [`get_mut`][get_mut], which will fail rather than cloning.
///
/// [weak]: struct.Weak.html
/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
/// [get_mut]: struct.Arc.html#method.get_mut
///
/// # Examples
///
@ -439,10 +506,9 @@ impl<T: Clone> Arc<T> {
/// *Arc::make_mut(&mut data) += 1; // Won't clone anything
/// *Arc::make_mut(&mut other_data) *= 2; // Won't clone anything
///
/// // Note: data and other_data now point to different numbers
/// // Now `data` and `other_data` point to different values.
/// assert_eq!(*data, 8);
/// assert_eq!(*other_data, 12);
///
/// ```
#[inline]
#[stable(feature = "arc_unique", since = "1.4.0")]
@ -501,8 +567,19 @@ impl<T: Clone> Arc<T> {
}
impl<T: ?Sized> Arc<T> {
/// Returns a mutable reference to the contained value if the `Arc<T>` has
/// one strong reference and no weak references.
/// Returns a mutable reference to the inner value, if there are
/// no other `Arc` or [`Weak`][weak] pointers to the same value.
///
/// Returns [`None`][option] otherwise, because it is not safe to
/// mutate a shared value.
///
/// See also [`make_mut`][make_mut], which will [`clone`][clone]
/// the inner value when it's shared.
///
/// [weak]: struct.Weak.html
/// [option]: ../../std/option/enum.Option.html
/// [make_mut]: struct.Arc.html#method.make_mut
/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
///
/// # Examples
///
@ -564,30 +641,32 @@ impl<T: ?Sized> Arc<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Drop for Arc<T> {
/// Drops the `Arc<T>`.
/// Drops the `Arc`.
///
/// This will decrement the strong reference count. If the strong reference
/// count becomes zero and the only other references are `Weak<T>` ones,
/// `drop`s the inner value.
/// count reaches zero then the only other references (if any) are
/// [`Weak`][weak], so we `drop` the inner value.
///
/// [weak]: struct.Weak.html
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// {
/// let five = Arc::new(5);
/// struct Foo;
///
/// // stuff
///
/// drop(five); // explicit drop
/// impl Drop for Foo {
/// fn drop(&mut self) {
/// println!("dropped!");
/// }
/// }
/// {
/// let five = Arc::new(5);
///
/// // stuff
/// let foo = Arc::new(Foo);
/// let foo2 = foo.clone();
///
/// } // implicit drop
/// drop(foo); // Doesn't print anything
/// drop(foo2); // Prints "dropped!"
/// ```
#[unsafe_destructor_blind_to_params]
#[inline]
@ -625,10 +704,14 @@ impl<T: ?Sized> Drop for Arc<T> {
}
impl<T> Weak<T> {
/// Constructs a new `Weak<T>` without an accompanying instance of T.
/// Constructs a new `Weak<T>`, without an accompanying instance of `T`.
///
/// This allocates memory for T, but does not initialize it. Calling
/// Weak<T>::upgrade() on the return value always gives None.
/// This allocates memory for `T`, but does not initialize it. Calling
/// [`upgrade`][upgrade] on the return value always gives
/// [`None`][option].
///
/// [upgrade]: struct.Weak.html#method.upgrade
/// [option]: ../../std/option/enum.Option.html
///
/// # Examples
///
@ -636,6 +719,7 @@ impl<T> Weak<T> {
/// use std::sync::Weak;
///
/// let empty: Weak<i64> = Weak::new();
/// assert!(empty.upgrade().is_none());
/// ```
#[stable(feature = "downgraded_weak", since = "1.10.0")]
pub fn new() -> Weak<T> {
@ -652,12 +736,13 @@ impl<T> Weak<T> {
}
impl<T: ?Sized> Weak<T> {
/// Upgrades a weak reference to a strong reference.
/// Upgrades the `Weak` pointer to an [`Arc`][arc], if possible.
///
/// Upgrades the `Weak<T>` reference to an `Arc<T>`, if possible.
/// Returns [`None`][option] if the strong count has reached zero and the
/// inner value was destroyed.
///
/// Returns `None` if there were no strong references and the data was
/// destroyed.
/// [arc]: struct.Arc.html
/// [option]: ../../std/option/enum.Option.html
///
/// # Examples
///
@ -669,6 +754,13 @@ impl<T: ?Sized> Weak<T> {
/// let weak_five = Arc::downgrade(&five);
///
/// let strong_five: Option<Arc<_>> = weak_five.upgrade();
/// assert!(strong_five.is_some());
///
/// // Destroy all strong pointers.
/// drop(strong_five);
/// drop(five);
///
/// assert!(weak_five.upgrade().is_none());
/// ```
#[stable(feature = "arc_weak", since = "1.4.0")]
pub fn upgrade(&self) -> Option<Arc<T>> {
@ -711,9 +803,10 @@ impl<T: ?Sized> Weak<T> {
#[stable(feature = "arc_weak", since = "1.4.0")]
impl<T: ?Sized> Clone for Weak<T> {
/// Makes a clone of the `Weak<T>`.
/// Makes a clone of the `Weak` pointer.
///
/// This increases the weak reference count.
/// This creates another pointer to the same inner value, increasing the
/// weak reference count.
///
/// # Examples
///
@ -745,7 +838,23 @@ impl<T: ?Sized> Clone for Weak<T> {
#[stable(feature = "downgraded_weak", since = "1.10.0")]
impl<T> Default for Weak<T> {
/// Constructs a new `Weak<T>` without an accompanying instance of T.
/// Constructs a new `Weak<T>`, without an accompanying instance of `T`.
///
/// This allocates memory for `T`, but does not initialize it. Calling
/// [`upgrade`][upgrade] on the return value always gives
/// [`None`][option].
///
/// [upgrade]: struct.Weak.html#method.upgrade
/// [option]: ../../std/option/enum.Option.html
///
/// # Examples
///
/// ```
/// use std::sync::Weak;
///
/// let empty: Weak<i64> = Default::default();
/// assert!(empty.upgrade().is_none());
/// ```
fn default() -> Weak<T> {
Weak::new()
}
@ -753,7 +862,7 @@ impl<T> Default for Weak<T> {
#[stable(feature = "arc_weak", since = "1.4.0")]
impl<T: ?Sized> Drop for Weak<T> {
/// Drops the `Weak<T>`.
/// Drops the `Weak` pointer.
///
/// This will decrement the weak reference count.
///
@ -762,21 +871,22 @@ impl<T: ?Sized> Drop for Weak<T> {
/// ```
/// use std::sync::Arc;
///
/// {
/// let five = Arc::new(5);
/// let weak_five = Arc::downgrade(&five);
/// struct Foo;
///
/// // stuff
///
/// drop(weak_five); // explicit drop
/// impl Drop for Foo {
/// fn drop(&mut self) {
/// println!("dropped!");
/// }
/// }
/// {
/// let five = Arc::new(5);
/// let weak_five = Arc::downgrade(&five);
///
/// // stuff
/// let foo = Arc::new(Foo);
/// let weak_foo = Arc::downgrade(&foo);
/// let other_weak_foo = weak_foo.clone();
///
/// } // implicit drop
/// drop(weak_foo); // Doesn't print anything
/// drop(foo); // Prints "dropped!"
///
/// assert!(other_weak_foo.upgrade().is_none());
/// ```
fn drop(&mut self) {
let ptr = *self.ptr;
@ -798,9 +908,9 @@ impl<T: ?Sized> Drop for Weak<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialEq> PartialEq for Arc<T> {
/// Equality for two `Arc<T>`s.
/// Equality for two `Arc`s.
///
/// Two `Arc<T>`s are equal if their inner value are equal.
/// Two `Arc`s are equal if their inner values are equal.
///
/// # Examples
///
@ -809,15 +919,15 @@ impl<T: ?Sized + PartialEq> PartialEq for Arc<T> {
///
/// let five = Arc::new(5);
///
/// five == Arc::new(5);
/// assert!(five == Arc::new(5));
/// ```
fn eq(&self, other: &Arc<T>) -> bool {
*(*self) == *(*other)
}
/// Inequality for two `Arc<T>`s.
/// Inequality for two `Arc`s.
///
/// Two `Arc<T>`s are unequal if their inner value are unequal.
/// Two `Arc`s are unequal if their inner values are unequal.
///
/// # Examples
///
@ -826,7 +936,7 @@ impl<T: ?Sized + PartialEq> PartialEq for Arc<T> {
///
/// let five = Arc::new(5);
///
/// five != Arc::new(5);
/// assert!(five != Arc::new(6));
/// ```
fn ne(&self, other: &Arc<T>) -> bool {
*(*self) != *(*other)
@ -834,7 +944,7 @@ impl<T: ?Sized + PartialEq> PartialEq for Arc<T> {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
/// Partial comparison for two `Arc<T>`s.
/// Partial comparison for two `Arc`s.
///
/// The two are compared by calling `partial_cmp()` on their inner values.
///
@ -842,16 +952,17 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
///
/// ```
/// use std::sync::Arc;
/// use std::cmp::Ordering;
///
/// let five = Arc::new(5);
///
/// five.partial_cmp(&Arc::new(5));
/// assert_eq!(Some(Ordering::Less), five.partial_cmp(&Arc::new(6)));
/// ```
fn partial_cmp(&self, other: &Arc<T>) -> Option<Ordering> {
(**self).partial_cmp(&**other)
}
/// Less-than comparison for two `Arc<T>`s.
/// Less-than comparison for two `Arc`s.
///
/// The two are compared by calling `<` on their inner values.
///
@ -862,13 +973,13 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
///
/// let five = Arc::new(5);
///
/// five < Arc::new(5);
/// assert!(five < Arc::new(6));
/// ```
fn lt(&self, other: &Arc<T>) -> bool {
*(*self) < *(*other)
}
/// 'Less-than or equal to' comparison for two `Arc<T>`s.
/// 'Less than or equal to' comparison for two `Arc`s.
///
/// The two are compared by calling `<=` on their inner values.
///
@ -879,13 +990,13 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
///
/// let five = Arc::new(5);
///
/// five <= Arc::new(5);
/// assert!(five <= Arc::new(5));
/// ```
fn le(&self, other: &Arc<T>) -> bool {
*(*self) <= *(*other)
}
/// Greater-than comparison for two `Arc<T>`s.
/// Greater-than comparison for two `Arc`s.
///
/// The two are compared by calling `>` on their inner values.
///
@ -896,13 +1007,13 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
///
/// let five = Arc::new(5);
///
/// five > Arc::new(5);
/// assert!(five > Arc::new(4));
/// ```
fn gt(&self, other: &Arc<T>) -> bool {
*(*self) > *(*other)
}
/// 'Greater-than or equal to' comparison for two `Arc<T>`s.
/// 'Greater than or equal to' comparison for two `Arc`s.
///
/// The two are compared by calling `>=` on their inner values.
///
@ -913,7 +1024,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
///
/// let five = Arc::new(5);
///
/// five >= Arc::new(5);
/// assert!(five >= Arc::new(5));
/// ```
fn ge(&self, other: &Arc<T>) -> bool {
*(*self) >= *(*other)
@ -921,6 +1032,20 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Ord> Ord for Arc<T> {
/// Comparison for two `Arc`s.
///
/// The two are compared by calling `cmp()` on their inner values.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use std::cmp::Ordering;
///
/// let five = Arc::new(5);
///
/// assert_eq!(Ordering::Less, five.cmp(&Arc::new(6)));
/// ```
fn cmp(&self, other: &Arc<T>) -> Ordering {
(**self).cmp(&**other)
}
@ -951,7 +1076,16 @@ impl<T: ?Sized> fmt::Pointer for Arc<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Default> Default for Arc<T> {
/// Creates a new `Arc<T>`, with the `Default` value for T.
/// Creates a new `Arc<T>`, with the `Default` value for `T`.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// let x: Arc<i32> = Default::default();
/// assert_eq!(*x, 0);
/// ```
fn default() -> Arc<T> {
Arc::new(Default::default())
}
@ -1002,6 +1136,7 @@ mod tests {
}
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
fn manually_share_arc() {
let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let arc_v = Arc::new(v);

View file

@ -244,12 +244,14 @@ impl<T: ?Sized> Box<T> {
/// the destructor of `T` and free the allocated memory. Since the
/// way `Box` allocates and releases memory is unspecified, the
/// only valid pointer to pass to this function is the one taken
/// from another `Box` via the `Box::into_raw` function.
/// from another `Box` via the [`Box::into_raw`] function.
///
/// This function is unsafe because improper use may lead to
/// memory problems. For example, a double-free may occur if the
/// function is called twice on the same raw pointer.
///
/// [`Box::into_raw`]: struct.Box.html#method.into_raw
///
/// # Examples
///
/// ```
@ -269,12 +271,14 @@ impl<T: ?Sized> Box<T> {
/// memory previously managed by the `Box`. In particular, the
/// caller should properly destroy `T` and release the memory. The
/// proper way to do so is to convert the raw pointer back into a
/// `Box` with the `Box::from_raw` function.
/// `Box` with the [`Box::from_raw`] function.
///
/// Note: this is an associated function, which means that you have
/// to call it as `Box::into_raw(b)` instead of `b.into_raw()`. This
/// is so that there is no conflict with a method on the inner type.
///
/// [`Box::from_raw`]: struct.Box.html#method.from_raw
///
/// # Examples
///
/// ```

View file

@ -88,7 +88,6 @@
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unique)]
#![cfg_attr(stage0, feature(unsafe_no_drop_flag))]
#![feature(unsize)]
#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol))]

View file

@ -44,7 +44,6 @@ use core::cmp;
/// `shrink_to_fit`, and `from_box` will actually set RawVec's private capacity
/// field. This allows zero-sized types to not be special-cased by consumers of
/// this type.
#[cfg_attr(stage0, unsafe_no_drop_flag)]
pub struct RawVec<T> {
ptr: Unique<T>,
cap: usize,
@ -58,11 +57,7 @@ impl<T> RawVec<T> {
pub fn new() -> Self {
unsafe {
// !0 is usize::MAX. This branch should be stripped at compile time.
let cap = if mem::size_of::<T>() == 0 {
!0
} else {
0
};
let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
// heap::EMPTY doubles as "unallocated" and "zero-sized allocation"
RawVec {
@ -210,11 +205,7 @@ impl<T> RawVec<T> {
let (new_cap, ptr) = if self.cap == 0 {
// skip to 4 because tiny Vec's are dumb; but not if that would cause overflow
let new_cap = if elem_size > (!0) / 8 {
1
} else {
4
};
let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
let ptr = heap::allocate(new_cap * elem_size, align);
(new_cap, ptr)
} else {
@ -348,7 +339,7 @@ impl<T> RawVec<T> {
let elem_size = mem::size_of::<T>();
// Nothing we can really do about these checks :(
let required_cap = used_cap.checked_add(needed_extra_cap)
.expect("capacity overflow");
.expect("capacity overflow");
// Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`.
let double_cap = self.cap * 2;
// `double_cap` guarantees exponential growth.

View file

@ -10,90 +10,139 @@
#![allow(deprecated)]
//! Unsynchronized reference-counted boxes (the `Rc<T>` type) which are usable
//! only within a single thread.
//! Single-threaded reference-counting pointers.
//!
//! The `Rc<T>` type provides shared ownership of an immutable value.
//! Destruction is deterministic, and will occur as soon as the last owner is
//! gone. It is marked as non-sendable because it avoids the overhead of atomic
//! reference counting.
//! The type [`Rc<T>`][rc] provides shared ownership of a value of type `T`,
//! allocated in the heap. Invoking [`clone`][clone] on `Rc` produces a new
//! pointer to the same value in the heap. When the last `Rc` pointer to a
//! given value is destroyed, the pointed-to value is also destroyed.
//!
//! The `downgrade` method can be used to create a non-owning `Weak<T>` pointer
//! to the box. A `Weak<T>` pointer can be upgraded to an `Rc<T>` pointer, but
//! will return `None` if the value has already been dropped.
//! Shared references in Rust disallow mutation by default, and `Rc` is no
//! exception. If you need to mutate through an `Rc`, use [`Cell`][cell] or
//! [`RefCell`][refcell].
//!
//! For example, a tree with parent pointers can be represented by putting the
//! nodes behind strong `Rc<T>` pointers, and then storing the parent pointers
//! as `Weak<T>` pointers.
//! `Rc` uses non-atomic reference counting. This means that overhead is very
//! low, but an `Rc` cannot be sent between threads, and consequently `Rc`
//! does not implement [`Send`][send]. As a result, the Rust compiler
//! will check *at compile time* that you are not sending `Rc`s between
//! threads. If you need multi-threaded, atomic reference counting, use
//! [`sync::Arc`][arc].
//!
//! The [`downgrade`][downgrade] method can be used to create a non-owning
//! [`Weak`][weak] pointer. A `Weak` pointer can be [`upgrade`][upgrade]d
//! to an `Rc`, but this will return [`None`][option] if the value has
//! already been dropped.
//!
//! A cycle between `Rc` pointers will never be deallocated. For this reason,
//! `Weak` is used to break cycles. For example, a tree could have strong
//! `Rc` pointers from parent nodes to children, and `Weak` pointers from
//! children back to their parents.
//!
//! `Rc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait),
//! so you can call `T`'s methods on a value of type `Rc<T>`. To avoid name
//! clashes with `T`'s methods, the methods of `Rc<T>` itself are [associated
//! functions][assoc], called using function-like syntax:
//!
//! ```
//! use std::rc::Rc;
//! let my_rc = Rc::new(());
//!
//! Rc::downgrade(&my_rc);
//! ```
//!
//! `Weak<T>` does not auto-dereference to `T`, because the value may have
//! already been destroyed.
//!
//! [rc]: struct.Rc.html
//! [weak]: struct.Weak.html
//! [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
//! [cell]: ../../std/cell/struct.Cell.html
//! [refcell]: ../../std/cell/struct.RefCell.html
//! [send]: ../../std/marker/trait.Send.html
//! [arc]: ../../std/sync/struct.Arc.html
//! [deref]: ../../std/ops/trait.Deref.html
//! [downgrade]: struct.Rc.html#method.downgrade
//! [upgrade]: struct.Weak.html#method.upgrade
//! [option]: ../../std/option/enum.Option.html
//! [assoc]: ../../book/method-syntax.html#associated-functions
//!
//! # Examples
//!
//! Consider a scenario where a set of `Gadget`s are owned by a given `Owner`.
//! We want to have our `Gadget`s point to their `Owner`. We can't do this with
//! unique ownership, because more than one gadget may belong to the same
//! `Owner`. `Rc<T>` allows us to share an `Owner` between multiple `Gadget`s,
//! `Owner`. `Rc` allows us to share an `Owner` between multiple `Gadget`s,
//! and have the `Owner` remain allocated as long as any `Gadget` points at it.
//!
//! ```rust
//! ```
//! use std::rc::Rc;
//!
//! struct Owner {
//! name: String
//! name: String,
//! // ...other fields
//! }
//!
//! struct Gadget {
//! id: i32,
//! owner: Rc<Owner>
//! owner: Rc<Owner>,
//! // ...other fields
//! }
//!
//! fn main() {
//! // Create a reference counted Owner.
//! let gadget_owner : Rc<Owner> = Rc::new(
//! Owner { name: String::from("Gadget Man") }
//! // Create a reference-counted `Owner`.
//! let gadget_owner: Rc<Owner> = Rc::new(
//! Owner {
//! name: "Gadget Man".to_string(),
//! }
//! );
//!
//! // Create Gadgets belonging to gadget_owner. To increment the reference
//! // count we clone the `Rc<T>` object.
//! let gadget1 = Gadget { id: 1, owner: gadget_owner.clone() };
//! let gadget2 = Gadget { id: 2, owner: gadget_owner.clone() };
//! // Create `Gadget`s belonging to `gadget_owner`. Cloning the `Rc<Owner>`
//! // value gives us a new pointer to the same `Owner` value, incrementing
//! // the reference count in the process.
//! let gadget1 = Gadget {
//! id: 1,
//! owner: gadget_owner.clone(),
//! };
//! let gadget2 = Gadget {
//! id: 2,
//! owner: gadget_owner.clone(),
//! };
//!
//! // Dispose of our local variable `gadget_owner`.
//! drop(gadget_owner);
//!
//! // Despite dropping gadget_owner, we're still able to print out the name
//! // of the Owner of the Gadgets. This is because we've only dropped the
//! // reference count object, not the Owner it wraps. As long as there are
//! // other `Rc<T>` objects pointing at the same Owner, it will remain
//! // allocated. Notice that the `Rc<T>` wrapper around Gadget.owner gets
//! // automatically dereferenced for us.
//! // Despite dropping `gadget_owner`, we're still able to print out the name
//! // of the `Owner` of the `Gadget`s. This is because we've only dropped a
//! // single `Rc<Owner>`, not the `Owner` it points to. As long as there are
//! // other `Rc<Owner>` values pointing at the same `Owner`, it will remain
//! // allocated. The field projection `gadget1.owner.name` works because
//! // `Rc<Owner>` automatically dereferences to `Owner`.
//! println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name);
//! println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name);
//!
//! // At the end of the method, gadget1 and gadget2 get destroyed, and with
//! // them the last counted references to our Owner. Gadget Man now gets
//! // destroyed as well.
//! // At the end of the function, `gadget1` and `gadget2` are destroyed, and
//! // with them the last counted references to our `Owner`. Gadget Man now
//! // gets destroyed as well.
//! }
//! ```
//!
//! If our requirements change, and we also need to be able to traverse from
//! Owner → Gadget, we will run into problems: an `Rc<T>` pointer from Owner
//!  Gadget introduces a cycle between the objects. This means that their
//! reference counts can never reach 0, and the objects will remain allocated: a
//! memory leak. In order to get around this, we can use `Weak<T>` pointers.
//! These pointers don't contribute to the total count.
//! `Owner` to `Gadget`, we will run into problems. An `Rc` pointer from `Owner`
//! to `Gadget` introduces a cycle between the values. This means that their
//! reference counts can never reach 0, and the values will remain allocated
//! forever: a memory leak. In order to get around this, we can use `Weak`
//! pointers.
//!
//! Rust actually makes it somewhat difficult to produce this loop in the first
//! place: in order to end up with two objects that point at each other, one of
//! them needs to be mutable. This is problematic because `Rc<T>` enforces
//! memory safety by only giving out shared references to the object it wraps,
//! place. In order to end up with two values that point at each other, one of
//! them needs to be mutable. This is difficult because `Rc` enforces
//! memory safety by only giving out shared references to the value it wraps,
//! and these don't allow direct mutation. We need to wrap the part of the
//! object we wish to mutate in a `RefCell`, which provides *interior
//! value we wish to mutate in a [`RefCell`][refcell], which provides *interior
//! mutability*: a method to achieve mutability through a shared reference.
//! `RefCell` enforces Rust's borrowing rules at runtime. Read the `Cell`
//! documentation for more details on interior mutability.
//! `RefCell` enforces Rust's borrowing rules at runtime.
//!
//! ```rust
//! ```
//! use std::rc::Rc;
//! use std::rc::Weak;
//! use std::cell::RefCell;
@ -111,41 +160,58 @@
//! }
//!
//! fn main() {
//! // Create a reference counted Owner. Note the fact that we've put the
//! // Owner's vector of Gadgets inside a RefCell so that we can mutate it
//! // through a shared reference.
//! let gadget_owner : Rc<Owner> = Rc::new(
//! // Create a reference-counted `Owner`. Note that we've put the `Owner`'s
//! // vector of `Gadget`s inside a `RefCell` so that we can mutate it through
//! // a shared reference.
//! let gadget_owner: Rc<Owner> = Rc::new(
//! Owner {
//! name: "Gadget Man".to_string(),
//! gadgets: RefCell::new(Vec::new()),
//! gadgets: RefCell::new(vec![]),
//! }
//! );
//!
//! // Create Gadgets belonging to gadget_owner as before.
//! let gadget1 = Rc::new(Gadget{id: 1, owner: gadget_owner.clone()});
//! let gadget2 = Rc::new(Gadget{id: 2, owner: gadget_owner.clone()});
//! // Create `Gadget`s belonging to `gadget_owner`, as before.
//! let gadget1 = Rc::new(
//! Gadget {
//! id: 1,
//! owner: gadget_owner.clone(),
//! }
//! );
//! let gadget2 = Rc::new(
//! Gadget {
//! id: 2,
//! owner: gadget_owner.clone(),
//! }
//! );
//!
//! // Add the Gadgets to their Owner. To do this we mutably borrow from
//! // the RefCell holding the Owner's Gadgets.
//! gadget_owner.gadgets.borrow_mut().push(Rc::downgrade(&gadget1));
//! gadget_owner.gadgets.borrow_mut().push(Rc::downgrade(&gadget2));
//! // Add the `Gadget`s to their `Owner`.
//! {
//! let mut gadgets = gadget_owner.gadgets.borrow_mut();
//! gadgets.push(Rc::downgrade(&gadget1));
//! gadgets.push(Rc::downgrade(&gadget2));
//!
//! // Iterate over our Gadgets, printing their details out
//! for gadget_opt in gadget_owner.gadgets.borrow().iter() {
//! // `RefCell` dynamic borrow ends here.
//! }
//!
//! // gadget_opt is a Weak<Gadget>. Since weak pointers can't guarantee
//! // that their object is still allocated, we need to call upgrade()
//! // on them to turn them into a strong reference. This returns an
//! // Option, which contains a reference to our object if it still
//! // exists.
//! let gadget = gadget_opt.upgrade().unwrap();
//! // Iterate over our `Gadget`s, printing their details out.
//! for gadget_weak in gadget_owner.gadgets.borrow().iter() {
//!
//! // `gadget_weak` is a `Weak<Gadget>`. Since `Weak` pointers can't
//! // guarantee the value is still allocated, we need to call
//! // `upgrade`, which returns an `Option<Rc<Gadget>>`.
//! //
//! // In this case we know the value still exists, so we simply
//! // `unwrap` the `Option`. In a more complicated program, you might
//! // need graceful error handling for a `None` result.
//!
//! let gadget = gadget_weak.upgrade().unwrap();
//! println!("Gadget {} owned by {}", gadget.id, gadget.owner.name);
//! }
//!
//! // At the end of the method, gadget_owner, gadget1 and gadget2 get
//! // destroyed. There are now no strong (`Rc<T>`) references to the gadgets.
//! // Once they get destroyed, the Gadgets get destroyed. This zeroes the
//! // reference count on Gadget Man, they get destroyed as well.
//! // At the end of the function, `gadget_owner`, `gadget1`, and `gadget2`
//! // are destroyed. There are now no strong (`Rc`) pointers to the
//! // gadgets, so they are destroyed. This zeroes the reference count on
//! // Gadget Man, so he gets destroyed as well.
//! }
//! ```
@ -164,13 +230,14 @@ use core::hash::{Hash, Hasher};
use core::intrinsics::{abort, assume};
use core::marker;
use core::marker::Unsize;
use core::mem::{self, align_of_val, forget, size_of_val, uninitialized};
use core::mem::{self, align_of_val, forget, size_of, size_of_val, uninitialized};
use core::ops::Deref;
use core::ops::CoerceUnsized;
use core::ptr::{self, Shared};
use core::convert::From;
use heap::deallocate;
use raw_vec::RawVec;
struct RcBox<T: ?Sized> {
strong: Cell<usize>,
@ -179,16 +246,14 @@ struct RcBox<T: ?Sized> {
}
/// A reference-counted pointer type over an immutable value.
/// A single-threaded reference-counting pointer.
///
/// See the [module level documentation](./index.html) for more details.
/// See the [module-level documentation](./index.html) for more details.
///
/// Note: the inherent methods defined on `Rc<T>` are all associated functions,
/// which means that you have to call them as e.g. `Rc::get_mut(&value)` instead
/// of `value.get_mut()`. This is so that there are no conflicts with methods
/// on the inner type `T`, which are what you want to call in the majority of
/// cases.
#[cfg_attr(stage0, unsafe_no_drop_flag)]
/// The inherent methods of `Rc` are all associated functions, which means
/// that you have to call them as e.g. `Rc::get_mut(&value)` instead of
/// `value.get_mut()`. This avoids conflicts with methods of the inner
/// type `T`.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Rc<T: ?Sized> {
ptr: Shared<RcBox<T>>,
@ -229,12 +294,15 @@ impl<T> Rc<T> {
}
}
/// Unwraps the contained value if the `Rc<T>` has exactly one strong reference.
/// Returns the contained value, if the `Rc` has exactly one strong reference.
///
/// Otherwise, an `Err` is returned with the same `Rc<T>`.
/// Otherwise, an [`Err`][result] is returned with the same `Rc` that was
/// passed in.
///
/// This will succeed even if there are outstanding weak references.
///
/// [result]: ../../std/result/enum.Result.html
///
/// # Examples
///
/// ```
@ -245,7 +313,7 @@ impl<T> Rc<T> {
///
/// let x = Rc::new(4);
/// let _y = x.clone();
/// assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4)));
/// assert_eq!(*Rc::try_unwrap(x).unwrap_err(), 4);
/// ```
#[inline]
#[stable(feature = "rc_unique", since = "1.4.0")]
@ -268,7 +336,11 @@ impl<T> Rc<T> {
}
}
/// Checks if `Rc::try_unwrap` would return `Ok`.
/// Checks whether [`Rc::try_unwrap`][try_unwrap] would return
/// [`Ok`][result].
///
/// [try_unwrap]: struct.Rc.html#method.try_unwrap
/// [result]: ../../std/result/enum.Result.html
///
/// # Examples
///
@ -284,7 +356,7 @@ impl<T> Rc<T> {
/// let x = Rc::new(4);
/// let _y = x.clone();
/// assert!(!Rc::would_unwrap(&x));
/// assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4)));
/// assert_eq!(*Rc::try_unwrap(x).unwrap_err(), 4);
/// ```
#[unstable(feature = "rc_would_unwrap",
reason = "just added for niche usecase",
@ -294,8 +366,35 @@ impl<T> Rc<T> {
}
}
impl Rc<str> {
/// Constructs a new `Rc<str>` from a string slice.
#[doc(hidden)]
#[unstable(feature = "rustc_private",
reason = "for internal use in rustc",
issue = "0")]
pub fn __from_str(value: &str) -> Rc<str> {
unsafe {
// Allocate enough space for `RcBox<str>`.
let aligned_len = 2 + (value.len() + size_of::<usize>() - 1) / size_of::<usize>();
let vec = RawVec::<usize>::with_capacity(aligned_len);
let ptr = vec.ptr();
forget(vec);
// Initialize fields of `RcBox<str>`.
*ptr.offset(0) = 1; // strong: Cell::new(1)
*ptr.offset(1) = 1; // weak: Cell::new(1)
ptr::copy_nonoverlapping(value.as_ptr(), ptr.offset(2) as *mut u8, value.len());
// Combine the allocation address and the string length into a fat pointer to `RcBox`.
let rcbox_ptr: *mut RcBox<str> = mem::transmute([ptr as usize, value.len()]);
assert!(aligned_len * size_of::<usize>() == size_of_val(&*rcbox_ptr));
Rc { ptr: Shared::new(rcbox_ptr) }
}
}
}
impl<T: ?Sized> Rc<T> {
/// Creates a new `Weak<T>` reference from this value.
/// Creates a new [`Weak`][weak] pointer to this value.
///
/// [weak]: struct.Weak.html
///
/// # Examples
///
@ -312,7 +411,22 @@ impl<T: ?Sized> Rc<T> {
Weak { ptr: this.ptr }
}
/// Get the number of weak references to this value.
/// Gets the number of [`Weak`][weak] pointers to this value.
///
/// [weak]: struct.Weak.html
///
/// # Examples
///
/// ```
/// #![feature(rc_counts)]
///
/// use std::rc::Rc;
///
/// let five = Rc::new(5);
/// let _weak_five = Rc::downgrade(&five);
///
/// assert_eq!(1, Rc::weak_count(&five));
/// ```
#[inline]
#[unstable(feature = "rc_counts", reason = "not clearly useful",
issue = "28356")]
@ -320,7 +434,20 @@ impl<T: ?Sized> Rc<T> {
this.weak() - 1
}
/// Get the number of strong references to this value.
/// Gets the number of strong (`Rc`) pointers to this value.
///
/// # Examples
///
/// ```
/// #![feature(rc_counts)]
///
/// use std::rc::Rc;
///
/// let five = Rc::new(5);
/// let _also_five = five.clone();
///
/// assert_eq!(2, Rc::strong_count(&five));
/// ```
#[inline]
#[unstable(feature = "rc_counts", reason = "not clearly useful",
issue = "28356")]
@ -328,8 +455,10 @@ impl<T: ?Sized> Rc<T> {
this.strong()
}
/// Returns true if there are no other `Rc` or `Weak<T>` values that share
/// the same inner value.
/// Returns true if there are no other `Rc` or [`Weak`][weak] pointers to
/// this inner value.
///
/// [weak]: struct.Weak.html
///
/// # Examples
///
@ -349,10 +478,19 @@ impl<T: ?Sized> Rc<T> {
Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1
}
/// Returns a mutable reference to the contained value if the `Rc<T>` has
/// one strong reference and no weak references.
/// Returns a mutable reference to the inner value, if there are
/// no other `Rc` or [`Weak`][weak] pointers to the same value.
///
/// Returns `None` if the `Rc<T>` is not unique.
/// Returns [`None`][option] otherwise, because it is not safe to
/// mutate a shared value.
///
/// See also [`make_mut`][make_mut], which will [`clone`][clone]
/// the inner value when it's shared.
///
/// [weak]: struct.Weak.html
/// [option]: ../../std/option/enum.Option.html
/// [make_mut]: struct.Rc.html#method.make_mut
/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
///
/// # Examples
///
@ -381,8 +519,8 @@ impl<T: ?Sized> Rc<T> {
#[unstable(feature = "ptr_eq",
reason = "newly added",
issue = "36497")]
/// Return whether two `Rc` references point to the same value
/// (not just values that compare equal).
/// Returns true if the two `Rc`s point to the same value (not
/// just values that compare as equal).
///
/// # Examples
///
@ -406,11 +544,17 @@ impl<T: ?Sized> Rc<T> {
}
impl<T: Clone> Rc<T> {
/// Make a mutable reference into the given `Rc<T>` by cloning the inner
/// data if the `Rc<T>` doesn't have one strong reference and no weak
/// references.
/// Makes a mutable reference into the given `Rc`.
///
/// This is also referred to as a copy-on-write.
/// If there are other `Rc` or [`Weak`][weak] pointers to the same value,
/// then `make_mut` will invoke [`clone`][clone] on the inner value to
/// ensure unique ownership. This is also referred to as clone-on-write.
///
/// See also [`get_mut`][get_mut], which will fail rather than cloning.
///
/// [weak]: struct.Weak.html
/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
/// [get_mut]: struct.Rc.html#method.get_mut
///
/// # Examples
///
@ -419,16 +563,15 @@ impl<T: Clone> Rc<T> {
///
/// let mut data = Rc::new(5);
///
/// *Rc::make_mut(&mut data) += 1; // Won't clone anything
/// let mut other_data = data.clone(); // Won't clone inner data
/// *Rc::make_mut(&mut data) += 1; // Clones inner data
/// *Rc::make_mut(&mut data) += 1; // Won't clone anything
/// *Rc::make_mut(&mut other_data) *= 2; // Won't clone anything
/// *Rc::make_mut(&mut data) += 1; // Won't clone anything
/// let mut other_data = data.clone(); // Won't clone inner data
/// *Rc::make_mut(&mut data) += 1; // Clones inner data
/// *Rc::make_mut(&mut data) += 1; // Won't clone anything
/// *Rc::make_mut(&mut other_data) *= 2; // Won't clone anything
///
/// // Note: data and other_data now point to different numbers
/// // Now `data` and `other_data` point to different values.
/// assert_eq!(*data, 8);
/// assert_eq!(*other_data, 12);
///
/// ```
#[inline]
#[stable(feature = "rc_unique", since = "1.4.0")]
@ -470,30 +613,32 @@ impl<T: ?Sized> Deref for Rc<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Drop for Rc<T> {
/// Drops the `Rc<T>`.
/// Drops the `Rc`.
///
/// This will decrement the strong reference count. If the strong reference
/// count becomes zero and the only other references are `Weak<T>` ones,
/// `drop`s the inner value.
/// count reaches zero then the only other references (if any) are
/// [`Weak`][weak], so we `drop` the inner value.
///
/// [weak]: struct.Weak.html
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// {
/// let five = Rc::new(5);
/// struct Foo;
///
/// // stuff
///
/// drop(five); // explicit drop
/// impl Drop for Foo {
/// fn drop(&mut self) {
/// println!("dropped!");
/// }
/// }
/// {
/// let five = Rc::new(5);
///
/// // stuff
/// let foo = Rc::new(Foo);
/// let foo2 = foo.clone();
///
/// } // implicit drop
/// drop(foo); // Doesn't print anything
/// drop(foo2); // Prints "dropped!"
/// ```
#[unsafe_destructor_blind_to_params]
fn drop(&mut self) {
@ -519,10 +664,10 @@ impl<T: ?Sized> Drop for Rc<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Clone for Rc<T> {
/// Makes a clone of the `Rc<T>`.
/// Makes a clone of the `Rc` pointer.
///
/// When you clone an `Rc<T>`, it will create another pointer to the data and
/// increase the strong reference counter.
/// This creates another pointer to the same inner value, increasing the
/// strong reference count.
///
/// # Examples
///
@ -550,6 +695,7 @@ impl<T: Default> Default for Rc<T> {
/// use std::rc::Rc;
///
/// let x: Rc<i32> = Default::default();
/// assert_eq!(*x, 0);
/// ```
#[inline]
fn default() -> Rc<T> {
@ -559,9 +705,9 @@ impl<T: Default> Default for Rc<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialEq> PartialEq for Rc<T> {
/// Equality for two `Rc<T>`s.
/// Equality for two `Rc`s.
///
/// Two `Rc<T>`s are equal if their inner value are equal.
/// Two `Rc`s are equal if their inner values are equal.
///
/// # Examples
///
@ -570,16 +716,16 @@ impl<T: ?Sized + PartialEq> PartialEq for Rc<T> {
///
/// let five = Rc::new(5);
///
/// five == Rc::new(5);
/// assert!(five == Rc::new(5));
/// ```
#[inline(always)]
fn eq(&self, other: &Rc<T>) -> bool {
**self == **other
}
/// Inequality for two `Rc<T>`s.
/// Inequality for two `Rc`s.
///
/// Two `Rc<T>`s are unequal if their inner value are unequal.
/// Two `Rc`s are unequal if their inner values are unequal.
///
/// # Examples
///
@ -588,7 +734,7 @@ impl<T: ?Sized + PartialEq> PartialEq for Rc<T> {
///
/// let five = Rc::new(5);
///
/// five != Rc::new(5);
/// assert!(five != Rc::new(6));
/// ```
#[inline(always)]
fn ne(&self, other: &Rc<T>) -> bool {
@ -601,7 +747,7 @@ impl<T: ?Sized + Eq> Eq for Rc<T> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialOrd> PartialOrd for Rc<T> {
/// Partial comparison for two `Rc<T>`s.
/// Partial comparison for two `Rc`s.
///
/// The two are compared by calling `partial_cmp()` on their inner values.
///
@ -609,17 +755,18 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Rc<T> {
///
/// ```
/// use std::rc::Rc;
/// use std::cmp::Ordering;
///
/// let five = Rc::new(5);
///
/// five.partial_cmp(&Rc::new(5));
/// assert_eq!(Some(Ordering::Less), five.partial_cmp(&Rc::new(6)));
/// ```
#[inline(always)]
fn partial_cmp(&self, other: &Rc<T>) -> Option<Ordering> {
(**self).partial_cmp(&**other)
}
/// Less-than comparison for two `Rc<T>`s.
/// Less-than comparison for two `Rc`s.
///
/// The two are compared by calling `<` on their inner values.
///
@ -630,14 +777,14 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Rc<T> {
///
/// let five = Rc::new(5);
///
/// five < Rc::new(5);
/// assert!(five < Rc::new(6));
/// ```
#[inline(always)]
fn lt(&self, other: &Rc<T>) -> bool {
**self < **other
}
/// 'Less-than or equal to' comparison for two `Rc<T>`s.
/// 'Less than or equal to' comparison for two `Rc`s.
///
/// The two are compared by calling `<=` on their inner values.
///
@ -648,14 +795,14 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Rc<T> {
///
/// let five = Rc::new(5);
///
/// five <= Rc::new(5);
/// assert!(five <= Rc::new(5));
/// ```
#[inline(always)]
fn le(&self, other: &Rc<T>) -> bool {
**self <= **other
}
/// Greater-than comparison for two `Rc<T>`s.
/// Greater-than comparison for two `Rc`s.
///
/// The two are compared by calling `>` on their inner values.
///
@ -666,14 +813,14 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Rc<T> {
///
/// let five = Rc::new(5);
///
/// five > Rc::new(5);
/// assert!(five > Rc::new(4));
/// ```
#[inline(always)]
fn gt(&self, other: &Rc<T>) -> bool {
**self > **other
}
/// 'Greater-than or equal to' comparison for two `Rc<T>`s.
/// 'Greater than or equal to' comparison for two `Rc`s.
///
/// The two are compared by calling `>=` on their inner values.
///
@ -684,7 +831,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Rc<T> {
///
/// let five = Rc::new(5);
///
/// five >= Rc::new(5);
/// assert!(five >= Rc::new(5));
/// ```
#[inline(always)]
fn ge(&self, other: &Rc<T>) -> bool {
@ -694,7 +841,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Rc<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Ord> Ord for Rc<T> {
/// Comparison for two `Rc<T>`s.
/// Comparison for two `Rc`s.
///
/// The two are compared by calling `cmp()` on their inner values.
///
@ -702,10 +849,11 @@ impl<T: ?Sized + Ord> Ord for Rc<T> {
///
/// ```
/// use std::rc::Rc;
/// use std::cmp::Ordering;
///
/// let five = Rc::new(5);
///
/// five.partial_cmp(&Rc::new(5));
/// assert_eq!(Ordering::Less, five.cmp(&Rc::new(6)));
/// ```
#[inline]
fn cmp(&self, other: &Rc<T>) -> Ordering {
@ -748,13 +896,18 @@ impl<T> From<T> for Rc<T> {
}
}
/// A weak version of `Rc<T>`.
/// A weak version of [`Rc`][rc].
///
/// Weak references do not count when determining if the inner value should be
/// dropped.
/// `Weak` pointers do not count towards determining if the inner value
/// should be dropped.
///
/// See the [module level documentation](./index.html) for more.
#[cfg_attr(stage0, unsafe_no_drop_flag)]
/// The typical way to obtain a `Weak` pointer is to call
/// [`Rc::downgrade`][downgrade].
///
/// See the [module-level documentation](./index.html) for more details.
///
/// [rc]: struct.Rc.html
/// [downgrade]: struct.Rc.html#method.downgrade
#[stable(feature = "rc_weak", since = "1.4.0")]
pub struct Weak<T: ?Sized> {
ptr: Shared<RcBox<T>>,
@ -769,10 +922,14 @@ impl<T: ?Sized> !marker::Sync for Weak<T> {}
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
impl<T> Weak<T> {
/// Constructs a new `Weak<T>` without an accompanying instance of T.
/// Constructs a new `Weak<T>`, without an accompanying instance of `T`.
///
/// This allocates memory for T, but does not initialize it. Calling
/// Weak<T>::upgrade() on the return value always gives None.
/// This allocates memory for `T`, but does not initialize it. Calling
/// [`upgrade`][upgrade] on the return value always gives
/// [`None`][option].
///
/// [upgrade]: struct.Weak.html#method.upgrade
/// [option]: ../../std/option/enum.Option.html
///
/// # Examples
///
@ -780,6 +937,7 @@ impl<T> Weak<T> {
/// use std::rc::Weak;
///
/// let empty: Weak<i64> = Weak::new();
/// assert!(empty.upgrade().is_none());
/// ```
#[stable(feature = "downgraded_weak", since = "1.10.0")]
pub fn new() -> Weak<T> {
@ -796,12 +954,13 @@ impl<T> Weak<T> {
}
impl<T: ?Sized> Weak<T> {
/// Upgrades a weak reference to a strong reference.
/// Upgrades the `Weak` pointer to an [`Rc`][rc], if possible.
///
/// Upgrades the `Weak<T>` reference to an `Rc<T>`, if possible.
/// Returns [`None`][option] if the strong count has reached zero and the
/// inner value was destroyed.
///
/// Returns `None` if there were no strong references and the data was
/// destroyed.
/// [rc]: struct.Rc.html
/// [option]: ../../std/option/enum.Option.html
///
/// # Examples
///
@ -813,6 +972,13 @@ impl<T: ?Sized> Weak<T> {
/// let weak_five = Rc::downgrade(&five);
///
/// let strong_five: Option<Rc<_>> = weak_five.upgrade();
/// assert!(strong_five.is_some());
///
/// // Destroy all strong pointers.
/// drop(strong_five);
/// drop(five);
///
/// assert!(weak_five.upgrade().is_none());
/// ```
#[stable(feature = "rc_weak", since = "1.4.0")]
pub fn upgrade(&self) -> Option<Rc<T>> {
@ -827,7 +993,7 @@ impl<T: ?Sized> Weak<T> {
#[stable(feature = "rc_weak", since = "1.4.0")]
impl<T: ?Sized> Drop for Weak<T> {
/// Drops the `Weak<T>`.
/// Drops the `Weak` pointer.
///
/// This will decrement the weak reference count.
///
@ -836,21 +1002,22 @@ impl<T: ?Sized> Drop for Weak<T> {
/// ```
/// use std::rc::Rc;
///
/// {
/// let five = Rc::new(5);
/// let weak_five = Rc::downgrade(&five);
/// struct Foo;
///
/// // stuff
///
/// drop(weak_five); // explicit drop
/// impl Drop for Foo {
/// fn drop(&mut self) {
/// println!("dropped!");
/// }
/// }
/// {
/// let five = Rc::new(5);
/// let weak_five = Rc::downgrade(&five);
///
/// // stuff
/// let foo = Rc::new(Foo);
/// let weak_foo = Rc::downgrade(&foo);
/// let other_weak_foo = weak_foo.clone();
///
/// } // implicit drop
/// drop(weak_foo); // Doesn't print anything
/// drop(foo); // Prints "dropped!"
///
/// assert!(other_weak_foo.upgrade().is_none());
/// ```
fn drop(&mut self) {
unsafe {
@ -868,9 +1035,10 @@ impl<T: ?Sized> Drop for Weak<T> {
#[stable(feature = "rc_weak", since = "1.4.0")]
impl<T: ?Sized> Clone for Weak<T> {
/// Makes a clone of the `Weak<T>`.
/// Makes a clone of the `Weak` pointer.
///
/// This increases the weak reference count.
/// This creates another pointer to the same inner value, increasing the
/// weak reference count.
///
/// # Examples
///
@ -897,7 +1065,23 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
#[stable(feature = "downgraded_weak", since = "1.10.0")]
impl<T> Default for Weak<T> {
/// Creates a new `Weak<T>`.
/// Constructs a new `Weak<T>`, without an accompanying instance of `T`.
///
/// This allocates memory for `T`, but does not initialize it. Calling
/// [`upgrade`][upgrade] on the return value always gives
/// [`None`][option].
///
/// [upgrade]: struct.Weak.html#method.upgrade
/// [option]: ../../std/option/enum.Option.html
///
/// # Examples
///
/// ```
/// use std::rc::Weak;
///
/// let empty: Weak<i64> = Default::default();
/// assert!(empty.upgrade().is_none());
/// ```
fn default() -> Weak<T> {
Weak::new()
}

View file

@ -22,11 +22,25 @@ fn main() {
println!("cargo:rustc-cfg=cargobuild");
println!("cargo:rerun-if-changed=build.rs");
let target = env::var("TARGET").unwrap();
let host = env::var("HOST").unwrap();
let target = env::var("TARGET").expect("TARGET was not set");
let host = env::var("HOST").expect("HOST was not set");
let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let src_dir = env::current_dir().unwrap();
// FIXME: This is a hack to support building targets that don't
// support jemalloc alongside hosts that do. The jemalloc build is
// controlled by a feature of the std crate, and if that feature
// changes between targets, it invalidates the fingerprint of
// std's build script (this is a cargo bug); so we must ensure
// that the feature set used by std is the same across all
// targets, which means we have to build the alloc_jemalloc crate
// for targets like emscripten, even if we don't use it.
if target.contains("rumprun") || target.contains("bitrig") || target.contains("openbsd") ||
target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") {
println!("cargo:rustc-cfg=dummy_jemalloc");
return;
}
if let Some(jemalloc) = env::var_os("JEMALLOC_OVERRIDE") {
let jemalloc = PathBuf::from(jemalloc);
println!("cargo:rustc-link-search=native={}",
@ -46,16 +60,16 @@ fn main() {
// only msvc returns None for ar so unwrap is okay
let ar = build_helper::cc2ar(compiler.path(), &target).unwrap();
let cflags = compiler.args()
.iter()
.map(|s| s.to_str().unwrap())
.collect::<Vec<_>>()
.join(" ");
.iter()
.map(|s| s.to_str().unwrap())
.collect::<Vec<_>>()
.join(" ");
let mut stack = src_dir.join("../jemalloc")
.read_dir()
.unwrap()
.map(|e| e.unwrap())
.collect::<Vec<_>>();
.read_dir()
.unwrap()
.map(|e| e.unwrap())
.collect::<Vec<_>>();
while let Some(entry) = stack.pop() {
let path = entry.path();
if entry.file_type().unwrap().is_dir() {
@ -137,10 +151,10 @@ fn main() {
run(&mut cmd);
run(Command::new("make")
.current_dir(&build_dir)
.arg("build_lib_static")
.arg("-j")
.arg(env::var("NUM_JOBS").unwrap()));
.current_dir(&build_dir)
.arg("build_lib_static")
.arg("-j")
.arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")));
if target.contains("windows") {
println!("cargo:rustc-link-lib=static=jemalloc");

View file

@ -23,124 +23,170 @@
extern crate libc;
use libc::{c_int, c_void, size_t};
pub use imp::*;
// Linkage directives to pull in jemalloc and its dependencies.
//
// On some platforms we need to be sure to link in `pthread` which jemalloc
// depends on, and specifically on android we need to also link to libgcc.
// Currently jemalloc is compiled with gcc which will generate calls to
// intrinsics that are libgcc specific (e.g. those intrinsics aren't present in
// libcompiler-rt), so link that in to get that support.
#[link(name = "jemalloc", kind = "static")]
#[cfg_attr(target_os = "android", link(name = "gcc"))]
#[cfg_attr(all(not(windows),
not(target_os = "android"),
not(target_env = "musl")),
link(name = "pthread"))]
#[cfg(not(cargobuild))]
extern "C" {}
// See comments in build.rs for why we sometimes build a crate that does nothing
#[cfg(not(dummy_jemalloc))]
mod imp {
use libc::{c_int, c_void, size_t};
// Note that the symbols here are prefixed by default on OSX and Windows (we
// don't explicitly request it), and on Android and DragonFly we explicitly
// request it as unprefixing cause segfaults (mismatches in allocators).
extern "C" {
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows"),
link_name = "je_mallocx")]
fn mallocx(size: size_t, flags: c_int) -> *mut c_void;
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows"),
link_name = "je_rallocx")]
fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows"),
link_name = "je_xallocx")]
fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows"),
link_name = "je_sdallocx")]
fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows"),
link_name = "je_nallocx")]
fn nallocx(size: size_t, flags: c_int) -> size_t;
}
// Linkage directives to pull in jemalloc and its dependencies.
//
// On some platforms we need to be sure to link in `pthread` which jemalloc
// depends on, and specifically on android we need to also link to libgcc.
// Currently jemalloc is compiled with gcc which will generate calls to
// intrinsics that are libgcc specific (e.g. those intrinsics aren't present in
// libcompiler-rt), so link that in to get that support.
#[link(name = "jemalloc", kind = "static")]
#[cfg_attr(target_os = "android", link(name = "gcc"))]
#[cfg_attr(all(not(windows),
not(target_os = "android"),
not(target_env = "musl")),
link(name = "pthread"))]
#[cfg(not(cargobuild))]
extern "C" {}
// The minimum alignment guaranteed by the architecture. This value is used to
// add fast paths for low alignment values. In practice, the alignment is a
// constant at the call site and the branch will be optimized out.
#[cfg(all(any(target_arch = "arm",
target_arch = "mips",
target_arch = "powerpc")))]
const MIN_ALIGN: usize = 8;
#[cfg(all(any(target_arch = "x86",
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "powerpc64",
target_arch = "mips64",
target_arch = "s390x")))]
const MIN_ALIGN: usize = 16;
// Note that the symbols here are prefixed by default on OSX and Windows (we
// don't explicitly request it), and on Android and DragonFly we explicitly
// request it as unprefixing cause segfaults (mismatches in allocators).
extern "C" {
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows"),
link_name = "je_mallocx")]
fn mallocx(size: size_t, flags: c_int) -> *mut c_void;
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows"),
link_name = "je_rallocx")]
fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows"),
link_name = "je_xallocx")]
fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows"),
link_name = "je_sdallocx")]
fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows"),
link_name = "je_nallocx")]
fn nallocx(size: size_t, flags: c_int) -> size_t;
}
// MALLOCX_ALIGN(a) macro
fn mallocx_align(a: usize) -> c_int {
a.trailing_zeros() as c_int
}
// The minimum alignment guaranteed by the architecture. This value is used to
// add fast paths for low alignment values. In practice, the alignment is a
// constant at the call site and the branch will be optimized out.
#[cfg(all(any(target_arch = "arm",
target_arch = "mips",
target_arch = "powerpc")))]
const MIN_ALIGN: usize = 8;
#[cfg(all(any(target_arch = "x86",
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "powerpc64",
target_arch = "mips64",
target_arch = "s390x")))]
const MIN_ALIGN: usize = 16;
fn align_to_flags(align: usize) -> c_int {
if align <= MIN_ALIGN {
// MALLOCX_ALIGN(a) macro
fn mallocx_align(a: usize) -> c_int {
a.trailing_zeros() as c_int
}
fn align_to_flags(align: usize) -> c_int {
if align <= MIN_ALIGN {
0
} else {
mallocx_align(align)
}
}
#[no_mangle]
pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
let flags = align_to_flags(align);
unsafe { mallocx(size as size_t, flags) as *mut u8 }
}
#[no_mangle]
pub extern "C" fn __rust_reallocate(ptr: *mut u8,
_old_size: usize,
size: usize,
align: usize)
-> *mut u8 {
let flags = align_to_flags(align);
unsafe { rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8 }
}
#[no_mangle]
pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8,
_old_size: usize,
size: usize,
align: usize)
-> usize {
let flags = align_to_flags(align);
unsafe { xallocx(ptr as *mut c_void, size as size_t, 0, flags) as usize }
}
#[no_mangle]
pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {
let flags = align_to_flags(align);
unsafe { sdallocx(ptr as *mut c_void, old_size as size_t, flags) }
}
#[no_mangle]
pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize {
let flags = align_to_flags(align);
unsafe { nallocx(size as size_t, flags) as usize }
}
// These symbols are used by jemalloc on android but the really old android
// we're building on doesn't have them defined, so just make sure the symbols
// are available.
#[no_mangle]
#[cfg(target_os = "android")]
pub extern "C" fn pthread_atfork(_prefork: *mut u8,
_postfork_parent: *mut u8,
_postfork_child: *mut u8)
-> i32 {
0
} else {
mallocx_align(align)
}
}
#[no_mangle]
pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
let flags = align_to_flags(align);
unsafe { mallocx(size as size_t, flags) as *mut u8 }
}
#[cfg(dummy_jemalloc)]
mod imp {
fn bogus() -> ! {
panic!("jemalloc is not implemented for this platform");
}
#[no_mangle]
pub extern "C" fn __rust_reallocate(ptr: *mut u8,
_old_size: usize,
size: usize,
align: usize)
-> *mut u8 {
let flags = align_to_flags(align);
unsafe { rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8 }
}
#[no_mangle]
pub extern "C" fn __rust_allocate(_size: usize, _align: usize) -> *mut u8 {
bogus()
}
#[no_mangle]
pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8,
_old_size: usize,
size: usize,
align: usize)
-> usize {
let flags = align_to_flags(align);
unsafe { xallocx(ptr as *mut c_void, size as size_t, 0, flags) as usize }
}
#[no_mangle]
pub extern "C" fn __rust_reallocate(_ptr: *mut u8,
_old_size: usize,
_size: usize,
_align: usize)
-> *mut u8 {
bogus()
}
#[no_mangle]
pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {
let flags = align_to_flags(align);
unsafe { sdallocx(ptr as *mut c_void, old_size as size_t, flags) }
}
#[no_mangle]
pub extern "C" fn __rust_reallocate_inplace(_ptr: *mut u8,
_old_size: usize,
_size: usize,
_align: usize)
-> usize {
bogus()
}
#[no_mangle]
pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize {
let flags = align_to_flags(align);
unsafe { nallocx(size as size_t, flags) as usize }
}
#[no_mangle]
pub extern "C" fn __rust_deallocate(_ptr: *mut u8, _old_size: usize, _align: usize) {
bogus()
}
// These symbols are used by jemalloc on android but the really old android
// we're building on doesn't have them defined, so just make sure the symbols
// are available.
#[no_mangle]
#[cfg(target_os = "android")]
pub extern "C" fn pthread_atfork(_prefork: *mut u8,
_postfork_parent: *mut u8,
_postfork_child: *mut u8)
-> i32 {
0
#[no_mangle]
pub extern "C" fn __rust_usable_size(_size: usize, _align: usize) -> usize {
bogus()
}
}

View file

@ -29,7 +29,8 @@
target_arch = "mips",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "asmjs")))]
target_arch = "asmjs",
target_arch = "wasm32")))]
const MIN_ALIGN: usize = 8;
#[cfg(all(any(target_arch = "x86_64",
target_arch = "aarch64",
@ -165,6 +166,7 @@ mod imp {
fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
fn GetLastError() -> DWORD;
}
#[repr(C)]
@ -220,11 +222,7 @@ mod imp {
HEAP_REALLOC_IN_PLACE_ONLY,
ptr as LPVOID,
size as SIZE_T) as *mut u8;
if new.is_null() {
old_size
} else {
size
}
if new.is_null() { old_size } else { size }
} else {
old_size
}
@ -233,11 +231,11 @@ mod imp {
pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, align: usize) {
if align <= MIN_ALIGN {
let err = HeapFree(GetProcessHeap(), 0, ptr as LPVOID);
debug_assert!(err != 0);
debug_assert!(err != 0, "Failed to free heap memory: {}", GetLastError());
} else {
let header = get_header(ptr);
let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID);
debug_assert!(err != 0);
debug_assert!(err != 0, "Failed to free heap memory: {}", GetLastError());
}
}

View file

@ -15,9 +15,8 @@
//! of individual objects while the arena itself is still alive. The benefit
//! of an arena is very fast allocation; just a pointer bump.
//!
//! This crate has two arenas implemented: `TypedArena`, which is a simpler
//! arena but can only hold objects of a single type, and `Arena`, which is a
//! more complex, slower arena which can hold objects of any type.
//! This crate implements `TypedArena`, a simple arena that can only hold
//! objects of a single type.
#![crate_name = "arena"]
#![unstable(feature = "rustc_private", issue = "27812")]
@ -47,11 +46,12 @@ use std::intrinsics;
use std::marker::{PhantomData, Send};
use std::mem;
use std::ptr;
use std::slice;
use alloc::heap;
use alloc::raw_vec::RawVec;
/// A faster arena that can hold objects of only one type.
/// An arena that can hold objects of only one type.
pub struct TypedArena<T> {
/// A pointer to the next object to be allocated.
ptr: Cell<*mut T>,
@ -60,7 +60,7 @@ pub struct TypedArena<T> {
/// reached, a new chunk is allocated.
end: Cell<*mut T>,
/// A vector arena segments.
/// A vector of arena chunks.
chunks: RefCell<Vec<TypedArenaChunk<T>>>,
/// Marker indicating that dropping the arena causes its owned
@ -69,7 +69,7 @@ pub struct TypedArena<T> {
}
struct TypedArenaChunk<T> {
/// Pointer to the next arena segment.
/// The raw storage for the arena chunk.
storage: RawVec<T>,
}
@ -117,26 +117,16 @@ impl<T> TypedArenaChunk<T> {
const PAGE: usize = 4096;
impl<T> TypedArena<T> {
/// Creates a new `TypedArena` with preallocated space for many objects.
/// Creates a new `TypedArena`.
#[inline]
pub fn new() -> TypedArena<T> {
// Reserve at least one page.
let elem_size = cmp::max(1, mem::size_of::<T>());
TypedArena::with_capacity(PAGE / elem_size)
}
/// Creates a new `TypedArena` with preallocated space for the given number of
/// objects.
#[inline]
pub fn with_capacity(capacity: usize) -> TypedArena<T> {
unsafe {
let chunk = TypedArenaChunk::<T>::new(cmp::max(1, capacity));
TypedArena {
ptr: Cell::new(chunk.start()),
end: Cell::new(chunk.end()),
chunks: RefCell::new(vec![chunk]),
_own: PhantomData,
}
TypedArena {
// We set both `ptr` and `end` to 0 so that the first call to
// alloc() will trigger a grow().
ptr: Cell::new(0 as *mut T),
end: Cell::new(0 as *mut T),
chunks: RefCell::new(vec![]),
_own: PhantomData,
}
}
@ -144,7 +134,7 @@ impl<T> TypedArena<T> {
#[inline]
pub fn alloc(&self, object: T) -> &mut T {
if self.ptr == self.end {
self.grow()
self.grow(1)
}
unsafe {
@ -165,35 +155,79 @@ impl<T> TypedArena<T> {
}
}
/// Allocates a slice of objects that are copy into the `TypedArena`, returning a mutable
/// reference to it. Will panic if passed a zero-sized types.
///
/// Panics:
/// - Zero-sized types
/// - Zero-length slices
#[inline]
pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
where T: Copy {
assert!(mem::size_of::<T>() != 0);
assert!(slice.len() != 0);
let available_capacity_bytes = self.end.get() as usize - self.ptr.get() as usize;
let at_least_bytes = slice.len() * mem::size_of::<T>();
if available_capacity_bytes < at_least_bytes {
self.grow(slice.len());
}
unsafe {
let start_ptr = self.ptr.get();
let arena_slice = slice::from_raw_parts_mut(start_ptr, slice.len());
self.ptr.set(start_ptr.offset(arena_slice.len() as isize));
arena_slice.copy_from_slice(slice);
arena_slice
}
}
/// Grows the arena.
#[inline(never)]
#[cold]
fn grow(&self) {
fn grow(&self, n: usize) {
unsafe {
let mut chunks = self.chunks.borrow_mut();
let prev_capacity = chunks.last().unwrap().storage.cap();
let new_capacity = prev_capacity.checked_mul(2).unwrap();
if chunks.last_mut().unwrap().storage.double_in_place() {
self.end.set(chunks.last().unwrap().end());
let (chunk, mut new_capacity);
if let Some(last_chunk) = chunks.last_mut() {
let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize;
let currently_used_cap = used_bytes / mem::size_of::<T>();
if last_chunk.storage.reserve_in_place(currently_used_cap, n) {
self.end.set(last_chunk.end());
return;
} else {
let prev_capacity = last_chunk.storage.cap();
loop {
new_capacity = prev_capacity.checked_mul(2).unwrap();
if new_capacity >= currently_used_cap + n {
break;
}
}
}
} else {
let chunk = TypedArenaChunk::<T>::new(new_capacity);
self.ptr.set(chunk.start());
self.end.set(chunk.end());
chunks.push(chunk);
let elem_size = cmp::max(1, mem::size_of::<T>());
new_capacity = cmp::max(n, PAGE / elem_size);
}
chunk = TypedArenaChunk::<T>::new(new_capacity);
self.ptr.set(chunk.start());
self.end.set(chunk.end());
chunks.push(chunk);
}
}
/// Clears the arena. Deallocates all but the longest chunk which may be reused.
pub fn clear(&mut self) {
unsafe {
// Clear the last chunk, which is partially filled.
let mut chunks_borrow = self.chunks.borrow_mut();
let last_idx = chunks_borrow.len() - 1;
self.clear_last_chunk(&mut chunks_borrow[last_idx]);
// If `T` is ZST, code below has no effect.
for mut chunk in chunks_borrow.drain(..last_idx) {
let cap = chunk.storage.cap();
chunk.destroy(cap);
if let Some(mut last_chunk) = chunks_borrow.pop() {
self.clear_last_chunk(&mut last_chunk);
// If `T` is ZST, code below has no effect.
for mut chunk in chunks_borrow.drain(..) {
let cap = chunk.storage.cap();
chunk.destroy(cap);
}
chunks_borrow.push(last_chunk);
}
}
}
@ -230,13 +264,14 @@ impl<T> Drop for TypedArena<T> {
unsafe {
// Determine how much was filled.
let mut chunks_borrow = self.chunks.borrow_mut();
let mut last_chunk = chunks_borrow.pop().unwrap();
// Drop the contents of the last chunk.
self.clear_last_chunk(&mut last_chunk);
// The last chunk will be dropped. Destroy all other chunks.
for chunk in chunks_borrow.iter_mut() {
let cap = chunk.storage.cap();
chunk.destroy(cap);
if let Some(mut last_chunk) = chunks_borrow.pop() {
// Drop the contents of the last chunk.
self.clear_last_chunk(&mut last_chunk);
// The last chunk will be dropped. Destroy all other chunks.
for chunk in chunks_borrow.iter_mut() {
let cap = chunk.storage.cap();
chunk.destroy(cap);
}
}
// RawVec handles deallocation of `last_chunk` and `self.chunks`.
}
@ -260,6 +295,12 @@ mod tests {
z: i32,
}
#[test]
pub fn test_unused() {
let arena: TypedArena<Point> = TypedArena::new();
assert!(arena.chunks.borrow().is_empty());
}
#[test]
fn test_arena_alloc_nested() {
struct Inner {
@ -296,9 +337,8 @@ mod tests {
let arena = Wrap(TypedArena::new());
let result = arena.alloc_outer(|| {
Outer { inner: arena.alloc_inner(|| Inner { value: 10 }) }
});
let result =
arena.alloc_outer(|| Outer { inner: arena.alloc_inner(|| Inner { value: 10 }) });
assert_eq!(result.inner.value, 10);
}

View file

@ -535,6 +535,7 @@ impl<T: Ord> BinaryHeap<T> {
///
/// ```
/// #![feature(binary_heap_extras)]
/// #![allow(deprecated)]
///
/// use std::collections::BinaryHeap;
/// let mut heap = BinaryHeap::new();
@ -549,6 +550,7 @@ impl<T: Ord> BinaryHeap<T> {
#[unstable(feature = "binary_heap_extras",
reason = "needs to be audited",
issue = "28147")]
#[rustc_deprecated(since = "1.13.0", reason = "use `peek_mut` instead")]
pub fn push_pop(&mut self, mut item: T) -> T {
match self.data.get_mut(0) {
None => return item,
@ -575,6 +577,7 @@ impl<T: Ord> BinaryHeap<T> {
///
/// ```
/// #![feature(binary_heap_extras)]
/// #![allow(deprecated)]
///
/// use std::collections::BinaryHeap;
/// let mut heap = BinaryHeap::new();
@ -587,6 +590,7 @@ impl<T: Ord> BinaryHeap<T> {
#[unstable(feature = "binary_heap_extras",
reason = "needs to be audited",
issue = "28147")]
#[rustc_deprecated(since = "1.13.0", reason = "use `peek_mut` instead")]
pub fn replace(&mut self, mut item: T) -> Option<T> {
if !self.is_empty() {
swap(&mut item, &mut self.data[0]);
@ -1029,7 +1033,7 @@ pub struct Drain<'a, T: 'a> {
iter: vec::Drain<'a, T>,
}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "drain", since = "1.6.0")]
impl<'a, T: 'a> Iterator for Drain<'a, T> {
type Item = T;
@ -1044,7 +1048,7 @@ impl<'a, T: 'a> Iterator for Drain<'a, T> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "drain", since = "1.6.0")]
impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<T> {
@ -1052,7 +1056,7 @@ impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "drain", since = "1.6.0")]
impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
#[unstable(feature = "fused", issue = "35602")]

View file

@ -14,7 +14,7 @@
use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
use core::ops::Deref;
use core::ops::{Add, AddAssign, Deref};
use fmt;
@ -86,16 +86,29 @@ impl<T> ToOwned for T where T: Clone {
/// ```
/// use std::borrow::Cow;
///
/// # #[allow(dead_code)]
/// fn abs_all(input: &mut Cow<[i32]>) {
/// for i in 0..input.len() {
/// let v = input[i];
/// if v < 0 {
/// // clones into a vector the first time (if not already owned)
/// // Clones into a vector if not already owned.
/// input.to_mut()[i] = -v;
/// }
/// }
/// }
///
/// // No clone occurs because `input` doesn't need to be mutated.
/// let slice = [0, 1, 2];
/// let mut input = Cow::from(&slice[..]);
/// abs_all(&mut input);
///
/// // Clone occurs because `input` needs to be mutated.
/// let slice = [-1, 0, 1];
/// let mut input = Cow::from(&slice[..]);
/// abs_all(&mut input);
///
/// // No clone occurs because `input` is already owned.
/// let mut input = Cow::from(vec![-1, 0, 1]);
/// abs_all(&mut input);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Cow<'a, B: ?Sized + 'a>
@ -270,3 +283,49 @@ impl<'a, T: ?Sized + ToOwned> AsRef<T> for Cow<'a, T> {
self
}
}
#[stable(feature = "cow_add", since = "1.13.0")]
impl<'a> Add<&'a str> for Cow<'a, str> {
type Output = Cow<'a, str>;
fn add(self, rhs: &'a str) -> Self {
if self == "" {
Cow::Borrowed(rhs)
} else if rhs == "" {
self
} else {
Cow::Owned(self.into_owned() + rhs)
}
}
}
#[stable(feature = "cow_add", since = "1.13.0")]
impl<'a> Add<Cow<'a, str>> for Cow<'a, str> {
type Output = Cow<'a, str>;
fn add(self, rhs: Cow<'a, str>) -> Self {
if self == "" {
rhs
} else if rhs == "" {
self
} else {
Cow::Owned(self.into_owned() + rhs.borrow())
}
}
}
#[stable(feature = "cow_add", since = "1.13.0")]
impl<'a> AddAssign<&'a str> for Cow<'a, str> {
fn add_assign(&mut self, rhs: &'a str) {
if rhs == "" { return; }
self.to_mut().push_str(rhs);
}
}
#[stable(feature = "cow_add", since = "1.13.0")]
impl<'a> AddAssign<Cow<'a, str>> for Cow<'a, str> {
fn add_assign(&mut self, rhs: Cow<'a, str>) {
if rhs == "" { return; }
self.to_mut().push_str(rhs.borrow());
}
}

View file

@ -136,6 +136,7 @@ pub struct BTreeMap<K, V> {
length: usize,
}
#[stable(feature = "btree_drop", since = "1.7.0")]
impl<K, V> Drop for BTreeMap<K, V> {
#[unsafe_destructor_blind_to_params]
fn drop(&mut self) {
@ -146,6 +147,7 @@ impl<K, V> Drop for BTreeMap<K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
fn clone(&self) -> BTreeMap<K, V> {
fn clone_subtree<K: Clone, V: Clone>(node: node::NodeRef<marker::Immut,
@ -1125,6 +1127,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K: 'a, V: 'a> IntoIterator for &'a BTreeMap<K, V> {
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
@ -1134,6 +1137,7 @@ impl<'a, K: 'a, V: 'a> IntoIterator for &'a BTreeMap<K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> {
type Item = (&'a K, &'a V);
@ -1154,6 +1158,7 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> {
#[unstable(feature = "fused", issue = "35602")]
impl<'a, K, V> FusedIterator for Iter<'a, K, V> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K: 'a, V: 'a> DoubleEndedIterator for Iter<'a, K, V> {
fn next_back(&mut self) -> Option<(&'a K, &'a V)> {
if self.length == 0 {
@ -1165,12 +1170,14 @@ impl<'a, K: 'a, V: 'a> DoubleEndedIterator for Iter<'a, K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K: 'a, V: 'a> ExactSizeIterator for Iter<'a, K, V> {
fn len(&self) -> usize {
self.length
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> Clone for Iter<'a, K, V> {
fn clone(&self) -> Iter<'a, K, V> {
Iter {
@ -1180,6 +1187,7 @@ impl<'a, K, V> Clone for Iter<'a, K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K: 'a, V: 'a> IntoIterator for &'a mut BTreeMap<K, V> {
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
@ -1189,6 +1197,7 @@ impl<'a, K: 'a, V: 'a> IntoIterator for &'a mut BTreeMap<K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K: 'a, V: 'a> Iterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
@ -1206,6 +1215,7 @@ impl<'a, K: 'a, V: 'a> Iterator for IterMut<'a, K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K: 'a, V: 'a> DoubleEndedIterator for IterMut<'a, K, V> {
fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> {
if self.length == 0 {
@ -1217,6 +1227,7 @@ impl<'a, K: 'a, V: 'a> DoubleEndedIterator for IterMut<'a, K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K: 'a, V: 'a> ExactSizeIterator for IterMut<'a, K, V> {
fn len(&self) -> usize {
self.length
@ -1226,6 +1237,7 @@ impl<'a, K: 'a, V: 'a> ExactSizeIterator for IterMut<'a, K, V> {
#[unstable(feature = "fused", issue = "35602")]
impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V> IntoIterator for BTreeMap<K, V> {
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
@ -1244,6 +1256,7 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
}
}
#[stable(feature = "btree_drop", since = "1.7.0")]
impl<K, V> Drop for IntoIter<K, V> {
fn drop(&mut self) {
for _ in &mut *self {
@ -1260,6 +1273,7 @@ impl<K, V> Drop for IntoIter<K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V> Iterator for IntoIter<K, V> {
type Item = (K, V);
@ -1304,6 +1318,7 @@ impl<K, V> Iterator for IntoIter<K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V> DoubleEndedIterator for IntoIter<K, V> {
fn next_back(&mut self) -> Option<(K, V)> {
if self.length == 0 {
@ -1342,6 +1357,7 @@ impl<K, V> DoubleEndedIterator for IntoIter<K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V> ExactSizeIterator for IntoIter<K, V> {
fn len(&self) -> usize {
self.length
@ -1351,6 +1367,7 @@ impl<K, V> ExactSizeIterator for IntoIter<K, V> {
#[unstable(feature = "fused", issue = "35602")]
impl<K, V> FusedIterator for IntoIter<K, V> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> Iterator for Keys<'a, K, V> {
type Item = &'a K;
@ -1363,12 +1380,14 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> {
fn next_back(&mut self) -> Option<&'a K> {
self.inner.next_back().map(|(k, _)| k)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {
fn len(&self) -> usize {
self.inner.len()
@ -1378,12 +1397,14 @@ impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {
#[unstable(feature = "fused", issue = "35602")]
impl<'a, K, V> FusedIterator for Keys<'a, K, V> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> Clone for Keys<'a, K, V> {
fn clone(&self) -> Keys<'a, K, V> {
Keys { inner: self.inner.clone() }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> Iterator for Values<'a, K, V> {
type Item = &'a V;
@ -1396,12 +1417,14 @@ impl<'a, K, V> Iterator for Values<'a, K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> {
fn next_back(&mut self) -> Option<&'a V> {
self.inner.next_back().map(|(_, v)| v)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
fn len(&self) -> usize {
self.inner.len()
@ -1411,6 +1434,7 @@ impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
#[unstable(feature = "fused", issue = "35602")]
impl<'a, K, V> FusedIterator for Values<'a, K, V> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> Clone for Values<'a, K, V> {
fn clone(&self) -> Values<'a, K, V> {
Values { inner: self.inner.clone() }
@ -1635,6 +1659,7 @@ impl<'a, K, V> RangeMut<'a, K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> BTreeMap<K, V> {
let mut map = BTreeMap::new();
@ -1643,6 +1668,7 @@ impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
#[inline]
fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
@ -1652,12 +1678,14 @@ impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
}
}
#[stable(feature = "extend_ref", since = "1.2.0")]
impl<'a, K: Ord + Copy, V: Copy> Extend<(&'a K, &'a V)> for BTreeMap<K, V> {
fn extend<I: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: I) {
self.extend(iter.into_iter().map(|(&key, &value)| (key, value)));
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Hash, V: Hash> Hash for BTreeMap<K, V> {
fn hash<H: Hasher>(&self, state: &mut H) {
for elt in self {
@ -1666,6 +1694,7 @@ impl<K: Hash, V: Hash> Hash for BTreeMap<K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Ord, V> Default for BTreeMap<K, V> {
/// Creates an empty `BTreeMap<K, V>`.
fn default() -> BTreeMap<K, V> {
@ -1673,14 +1702,17 @@ impl<K: Ord, V> Default for BTreeMap<K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: PartialEq, V: PartialEq> PartialEq for BTreeMap<K, V> {
fn eq(&self, other: &BTreeMap<K, V>) -> bool {
self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a == b)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Eq, V: Eq> Eq for BTreeMap<K, V> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: PartialOrd, V: PartialOrd> PartialOrd for BTreeMap<K, V> {
#[inline]
fn partial_cmp(&self, other: &BTreeMap<K, V>) -> Option<Ordering> {
@ -1688,6 +1720,7 @@ impl<K: PartialOrd, V: PartialOrd> PartialOrd for BTreeMap<K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Ord, V: Ord> Ord for BTreeMap<K, V> {
#[inline]
fn cmp(&self, other: &BTreeMap<K, V>) -> Ordering {
@ -1695,12 +1728,14 @@ impl<K: Ord, V: Ord> Ord for BTreeMap<K, V> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Debug, V: Debug> Debug for BTreeMap<K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_map().entries(self.iter()).finish()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K: Ord, Q: ?Sized, V> Index<&'a Q> for BTreeMap<K, V>
where K: Borrow<Q>,
Q: Ord

View file

@ -779,6 +779,7 @@ impl<T: Debug> Debug for BTreeSet<T> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Clone for Iter<'a, T> {
fn clone(&self) -> Iter<'a, T> {
Iter { iter: self.iter.clone() }
@ -864,6 +865,7 @@ fn cmp_opt<T: Ord>(x: Option<&T>, y: Option<&T>, short: Ordering, long: Ordering
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Clone for Difference<'a, T> {
fn clone(&self) -> Difference<'a, T> {
Difference {
@ -901,6 +903,7 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> {
#[unstable(feature = "fused", issue = "35602")]
impl<'a, T: Ord> FusedIterator for Difference<'a, T> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Clone for SymmetricDifference<'a, T> {
fn clone(&self) -> SymmetricDifference<'a, T> {
SymmetricDifference {
@ -934,6 +937,7 @@ impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> {
#[unstable(feature = "fused", issue = "35602")]
impl<'a, T: Ord> FusedIterator for SymmetricDifference<'a, T> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Clone for Intersection<'a, T> {
fn clone(&self) -> Intersection<'a, T> {
Intersection {
@ -977,6 +981,7 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> {
#[unstable(feature = "fused", issue = "35602")]
impl<'a, T: Ord> FusedIterator for Intersection<'a, T> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Clone for Union<'a, T> {
fn clone(&self) -> Union<'a, T> {
Union {

View file

@ -48,7 +48,6 @@ impl<E> Clone for EnumSet<E> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<E: CLike + fmt::Debug> fmt::Debug for EnumSet<E> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_set().entries(self).finish()
@ -277,7 +276,6 @@ impl<E: CLike> FromIterator<E> for EnumSet<E> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, E> IntoIterator for &'a EnumSet<E> where E: CLike
{
type Item = E;
@ -296,7 +294,6 @@ impl<E: CLike> Extend<E> for EnumSet<E> {
}
}
#[stable(feature = "extend_ref", since = "1.2.0")]
impl<'a, E: 'a + CLike + Copy> Extend<&'a E> for EnumSet<E> {
fn extend<I: IntoIterator<Item = &'a E>>(&mut self, iter: I) {
self.extend(iter.into_iter().cloned());

View file

@ -261,8 +261,8 @@
//! This and `writeln` are two macros which are used to emit the format string
//! to a specified stream. This is used to prevent intermediate allocations of
//! format strings and instead directly write the output. Under the hood, this
//! function is actually invoking the `write` function defined in this module.
//! Example usage is:
//! function is actually invoking the `write_fmt` function defined on the
//! `std::io::Write` trait. Example usage is:
//!
//! ```
//! # #![allow(unused_must_use)]
@ -327,7 +327,7 @@
//! format := '{' [ argument ] [ ':' format_spec ] '}'
//! argument := integer | identifier
//!
//! format_spec := [[fill]align][sign]['#'][0][width]['.' precision][type]
//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type]
//! fill := character
//! align := '<' | '^' | '>'
//! sign := '+' | '-'

View file

@ -52,7 +52,6 @@
#![feature(step_by)]
#![feature(unicode)]
#![feature(unique)]
#![cfg_attr(stage0, feature(unsafe_no_drop_flag))]
#![cfg_attr(test, feature(rand, test))]
#![no_std]

View file

@ -1294,6 +1294,7 @@ mod tests {
}
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
fn test_send() {
let n = list_from(&[1, 2, 3]);
thread::spawn(move || {

View file

@ -68,7 +68,9 @@ macro_rules! vec {
}
/// Use the syntax described in `std::fmt` to create a value of type `String`.
/// See `std::fmt` for more information.
/// See [`std::fmt`][fmt] for more information.
///
/// [fmt]: ../std/fmt/index.html
///
/// # Examples
///

View file

@ -36,7 +36,7 @@
//!
//! ## Structs
//!
//! There are several structs that are useful for slices, such as `Iter`, which
//! There are several structs that are useful for slices, such as [`Iter`], which
//! represents iteration over a slice.
//!
//! ## Trait Implementations
@ -44,9 +44,9 @@
//! There are several implementations of common traits for slices. Some examples
//! include:
//!
//! * `Clone`
//! * `Eq`, `Ord` - for slices whose element type are `Eq` or `Ord`.
//! * `Hash` - for slices whose element type is `Hash`
//! * [`Clone`]
//! * [`Eq`], [`Ord`] - for slices whose element type are [`Eq`] or [`Ord`].
//! * [`Hash`] - for slices whose element type is [`Hash`].
//!
//! ## Iteration
//!
@ -73,12 +73,24 @@
//! the element type of the slice is `i32`, the element type of the iterator is
//! `&mut i32`.
//!
//! * `.iter()` and `.iter_mut()` are the explicit methods to return the default
//! * [`.iter()`] and [`.iter_mut()`] are the explicit methods to return the default
//! iterators.
//! * Further methods that return iterators are `.split()`, `.splitn()`,
//! `.chunks()`, `.windows()` and more.
//! * Further methods that return iterators are [`.split()`], [`.splitn()`],
//! [`.chunks()`], [`.windows()`] and more.
//!
//! *[See also the slice primitive type](../../std/primitive.slice.html).*
//!
//! [`Clone`]: ../../std/clone/trait.Clone.html
//! [`Eq`]: ../../std/cmp/trait.Eq.html
//! [`Ord`]: ../../std/cmp/trait.Ord.html
//! [`Iter`]: struct.Iter.html
//! [`Hash`]: ../../std/hash/trait.Hash.html
//! [`.iter()`]: ../../std/primitive.slice.html#method.iter
//! [`.iter_mut()`]: ../../std/primitive.slice.html#method.iter_mut
//! [`.split()`]: ../../std/primitive.slice.html#method.split
//! [`.splitn()`]: ../../std/primitive.slice.html#method.splitn
//! [`.chunks()`]: ../../std/primitive.slice.html#method.chunks
//! [`.windows()`]: ../../std/primitive.slice.html#method.windows
#![stable(feature = "rust1", since = "1.0.0")]
// Many of the usings in this module are only used in the test configuration.
@ -168,7 +180,7 @@ impl<T> [T] {
core_slice::SliceExt::len(self)
}
/// Returns true if the slice has a length of 0
/// Returns true if the slice has a length of 0.
///
/// # Example
///
@ -402,7 +414,7 @@ impl<T> [T] {
core_slice::SliceExt::get_unchecked_mut(self, index)
}
/// Returns an raw pointer to the slice's buffer
/// Returns an raw pointer to the slice's buffer.
///
/// The caller must ensure that the slice outlives the pointer this
/// function returns, or else it will end up pointing to garbage.
@ -468,7 +480,7 @@ impl<T> [T] {
///
/// # Examples
///
/// ```rust
/// ```
/// let mut v = ["a", "b", "c", "d"];
/// v.swap(1, 3);
/// assert!(v == ["a", "d", "c", "b"]);
@ -483,7 +495,7 @@ impl<T> [T] {
///
/// # Example
///
/// ```rust
/// ```
/// let mut v = [1, 2, 3];
/// v.reverse();
/// assert!(v == [3, 2, 1]);
@ -567,9 +579,9 @@ impl<T> [T] {
}
/// Returns an iterator over `size` elements of the slice at a
/// time. The chunks are slices and do not overlap. If `size` does not divide the
/// length of the slice, then the last chunk will not have length
/// `size`.
/// time. The chunks are slices and do not overlap. If `size` does
/// not divide the length of the slice, then the last chunk will
/// not have length `size`.
///
/// # Panics
///
@ -656,7 +668,7 @@ impl<T> [T] {
///
/// # Examples
///
/// ```rust
/// ```
/// let mut v = [1, 2, 3, 4, 5, 6];
///
/// // scoped to restrict the lifetime of the borrows
@ -754,7 +766,7 @@ impl<T> [T] {
}
/// Returns an iterator over subslices separated by elements that match
/// `pred`, limited to returning at most `n` items. The matched element is
/// `pred`, limited to returning at most `n` items. The matched element is
/// not contained in the subslices.
///
/// The last element returned, if any, will contain the remainder of the
@ -781,7 +793,7 @@ impl<T> [T] {
}
/// Returns an iterator over subslices separated by elements that match
/// `pred`, limited to returning at most `n` items. The matched element is
/// `pred`, limited to returning at most `n` items. The matched element is
/// not contained in the subslices.
///
/// The last element returned, if any, will contain the remainder of the
@ -835,7 +847,7 @@ impl<T> [T] {
/// Returns an iterator over subslices separated by elements that match
/// `pred` limited to returning at most `n` items. This starts at the end of
/// the slice and works backwards. The matched element is not contained in
/// the slice and works backwards. The matched element is not contained in
/// the subslices.
///
/// The last element returned, if any, will contain the remainder of the
@ -922,9 +934,9 @@ impl<T> [T] {
///
/// Looks up a series of four elements. The first is found, with a
/// uniquely determined position; the second and third are not
/// found; the fourth could match any position in `[1,4]`.
/// found; the fourth could match any position in `[1, 4]`.
///
/// ```rust
/// ```
/// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
///
/// assert_eq!(s.binary_search(&13), Ok(9));
@ -956,9 +968,9 @@ impl<T> [T] {
///
/// Looks up a series of four elements. The first is found, with a
/// uniquely determined position; the second and third are not
/// found; the fourth could match any position in `[1,4]`.
/// found; the fourth could match any position in `[1, 4]`.
///
/// ```rust
/// ```
/// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
///
/// let seek = 13;
@ -982,21 +994,23 @@ impl<T> [T] {
/// Binary search a sorted slice with a key extraction function.
///
/// Assumes that the slice is sorted by the key, for instance with
/// `sort_by_key` using the same key extraction function.
/// [`sort_by_key`] using the same key extraction function.
///
/// If a matching value is found then returns `Ok`, containing the
/// index for the matched element; if no match is found then `Err`
/// is returned, containing the index where a matching element could
/// be inserted while maintaining sorted order.
///
/// [`sort_by_key`]: #method.sort_by_key
///
/// # Examples
///
/// Looks up a series of four elements in a slice of pairs sorted by
/// their second elements. The first is found, with a uniquely
/// determined position; the second and third are not found; the
/// fourth could match any position in `[1,4]`.
/// fourth could match any position in `[1, 4]`.
///
/// ```rust
/// ```
/// let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1),
/// (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
/// (1, 21), (2, 34), (4, 55)];
@ -1023,7 +1037,7 @@ impl<T> [T] {
///
/// # Examples
///
/// ```rust
/// ```
/// let mut v = [-5, 4, 1, -3, 2];
///
/// v.sort();
@ -1037,7 +1051,7 @@ impl<T> [T] {
self.sort_by(|a, b| a.cmp(b))
}
/// Sorts the slice, in place, using `key` to extract a key by which to
/// Sorts the slice, in place, using `f` to extract a key by which to
/// order the sort by.
///
/// This sort is stable and `O(n log n)` worst-case but allocates
@ -1045,7 +1059,7 @@ impl<T> [T] {
///
/// # Examples
///
/// ```rust
/// ```
/// let mut v = [-5i32, 4, 1, -3, 2];
///
/// v.sort_by_key(|k| k.abs());
@ -1067,7 +1081,7 @@ impl<T> [T] {
///
/// # Examples
///
/// ```rust
/// ```
/// let mut v = [5, 4, 1, 3, 2];
/// v.sort_by(|a, b| a.cmp(b));
/// assert!(v == [1, 2, 3, 4, 5]);
@ -1094,7 +1108,7 @@ impl<T> [T] {
///
/// # Example
///
/// ```rust
/// ```
/// let mut dst = [0, 0, 0];
/// let src = [1, 2, 3];
///
@ -1116,7 +1130,7 @@ impl<T> [T] {
///
/// # Example
///
/// ```rust
/// ```
/// let mut dst = [0, 0, 0];
/// let src = [1, 2, 3];
///
@ -1156,7 +1170,7 @@ impl<T> [T] {
/// let x = s.into_vec();
/// // `s` cannot be used anymore because it has been converted into `x`.
///
/// assert_eq!(x, vec!(10, 40, 30));
/// assert_eq!(x, vec![10, 40, 30]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]

View file

@ -122,7 +122,7 @@ pub struct EncodeUtf16<'a> {
encoder: Utf16Encoder<Chars<'a>>,
}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "encode_utf16", since = "1.8.0")]
impl<'a> Iterator for EncodeUtf16<'a> {
type Item = u16;
@ -697,7 +697,7 @@ impl str {
///
/// Basic usage:
///
/// ```rust
/// ```
/// let bananas = "bananas";
///
/// assert!(bananas.ends_with("anas"));
@ -900,7 +900,7 @@ impl str {
///
/// It does _not_ give you:
///
/// ```rust,ignore
/// ```,ignore
/// assert_eq!(d, &["a", "b", "c"]);
/// ```
///
@ -1053,10 +1053,10 @@ impl str {
}
/// An iterator over substrings of the given string slice, separated by a
/// pattern, restricted to returning at most `count` items.
/// pattern, restricted to returning at most `n` items.
///
/// The last element returned, if any, will contain the remainder of the
/// string slice.
/// If `n` substrings are returned, the last substring (the `n`th substring)
/// will contain the remainder of the string.
///
/// The pattern can be a `&str`, [`char`], or a closure that determines the
/// split.
@ -1098,16 +1098,16 @@ impl str {
/// assert_eq!(v, ["abc", "defXghi"]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> {
core_str::StrExt::splitn(self, count, pat)
pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> {
core_str::StrExt::splitn(self, n, pat)
}
/// An iterator over substrings of this string slice, separated by a
/// pattern, starting from the end of the string, restricted to returning
/// at most `count` items.
/// at most `n` items.
///
/// The last element returned, if any, will contain the remainder of the
/// string slice.
/// If `n` substrings are returned, the last substring (the `n`th substring)
/// will contain the remainder of the string.
///
/// The pattern can be a `&str`, [`char`], or a closure that
/// determines the split.
@ -1145,10 +1145,10 @@ impl str {
/// assert_eq!(v, ["ghi", "abc1def"]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P>
pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P>
where P::Searcher: ReverseSearcher<'a>
{
core_str::StrExt::rsplitn(self, count, pat)
core_str::StrExt::rsplitn(self, n, pat)
}
/// An iterator over the matches of a pattern within the given string
@ -1789,4 +1789,24 @@ impl str {
String::from_utf8_unchecked(slice.into_vec())
}
}
/// Create a [`String`] by repeating a string `n` times.
///
/// [`String`]: string/struct.String.html
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(repeat_str)]
///
/// assert_eq!("abc".repeat(4), String::from("abcabcabcabc"));
/// ```
#[unstable(feature = "repeat_str", issue = "37079")]
pub fn repeat(&self, n: usize) -> String {
let mut s = String::with_capacity(self.len() * n);
s.extend((0..n).map(|_| self));
s
}
}

View file

@ -14,24 +14,25 @@
//! [`ToString`]s, and several error types that may result from working with
//! [`String`]s.
//!
//! [`String`]: struct.String.html
//! [`ToString`]: trait.ToString.html
//!
//! # Examples
//!
//! There are multiple ways to create a new `String` from a string literal:
//! There are multiple ways to create a new [`String`] from a string literal:
//!
//! ```rust
//! ```
//! let s = "Hello".to_string();
//!
//! let s = String::from("world");
//! let s: String = "also this".into();
//! ```
//!
//! You can create a new `String` from an existing one by concatenating with
//! You can create a new [`String`] from an existing one by concatenating with
//! `+`:
//!
//! ```rust
//! [`String`]: struct.String.html
//!
//! ```
//! let s = "Hello".to_string();
//!
//! let message = s + " world!";
@ -40,7 +41,7 @@
//! If you have a vector of valid UTF-8 bytes, you can make a `String` out of
//! it. You can do the reverse too.
//!
//! ```rust
//! ```
//! let sparkle_heart = vec![240, 159, 146, 150];
//!
//! // We know these bytes are valid, so we'll use `unwrap()`.
@ -134,10 +135,10 @@ use boxed::Box;
/// Indexing is intended to be a constant-time operation, but UTF-8 encoding
/// does not allow us to do this. Furthermore, it's not clear what sort of
/// thing the index should return: a byte, a codepoint, or a grapheme cluster.
/// The [`as_bytes()`] and [`chars()`] methods return iterators over the first
/// The [`bytes()`] and [`chars()`] methods return iterators over the first
/// two, respectively.
///
/// [`as_bytes()`]: #method.as_bytes
/// [`bytes()`]: #method.bytes
/// [`chars()`]: #method.chars
///
/// # Deref
@ -975,7 +976,7 @@ impl String {
pub fn push(&mut self, ch: char) {
match ch.len_utf8() {
1 => self.vec.push(ch as u8),
_ => self.vec.extend_from_slice(ch.encode_utf8().as_slice()),
_ => self.vec.extend_from_slice(ch.encode_utf8(&mut [0;4]).as_bytes()),
}
}
@ -1131,10 +1132,11 @@ impl String {
let len = self.len();
assert!(idx <= len);
assert!(self.is_char_boundary(idx));
let bits = ch.encode_utf8();
let mut bits = [0; 4];
let bits = ch.encode_utf8(&mut bits).as_bytes();
unsafe {
self.insert_bytes(idx, bits.as_slice());
self.insert_bytes(idx, bits);
}
}
@ -1858,6 +1860,13 @@ impl<'a> From<&'a str> for String {
}
}
#[stable(feature = "string_from_cow_str", since = "1.14.0")]
impl<'a> From<Cow<'a, str>> for String {
fn from(s: Cow<'a, str>) -> String {
s.into_owned()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> From<&'a str> for Cow<'a, str> {
#[inline]
@ -1902,26 +1911,6 @@ impl Into<Vec<u8>> for String {
}
}
#[stable(feature = "stringfromchars", since = "1.12.0")]
impl<'a> From<&'a [char]> for String {
#[inline]
fn from(v: &'a [char]) -> String {
let mut s = String::with_capacity(v.len());
for c in v {
s.push(*c);
}
s
}
}
#[stable(feature = "stringfromchars", since = "1.12.0")]
impl From<Vec<char>> for String {
#[inline]
fn from(v: Vec<char>) -> String {
String::from(v.as_slice())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Write for String {
#[inline]

View file

@ -16,13 +16,13 @@
//!
//! # Examples
//!
//! You can explicitly create a `Vec<T>` with `new()`:
//! You can explicitly create a [`Vec<T>`] with [`new()`]:
//!
//! ```
//! let v: Vec<i32> = Vec::new();
//! ```
//!
//! ...or by using the `vec!` macro:
//! ...or by using the [`vec!`] macro:
//!
//! ```
//! let v: Vec<i32> = vec![];
@ -32,7 +32,7 @@
//! let v = vec![0; 10]; // ten zeroes
//! ```
//!
//! You can `push` values onto the end of a vector (which will grow the vector
//! You can [`push`] values onto the end of a vector (which will grow the vector
//! as needed):
//!
//! ```
@ -49,13 +49,20 @@
//! let two = v.pop();
//! ```
//!
//! Vectors also support indexing (through the `Index` and `IndexMut` traits):
//! Vectors also support indexing (through the [`Index`] and [`IndexMut`] traits):
//!
//! ```
//! let mut v = vec![1, 2, 3];
//! let three = v[2];
//! v[1] = v[1] + 5;
//! ```
//!
//! [`Vec<T>`]: ../../std/vec/struct.Vec.html
//! [`new()`]: ../../std/vec/struct.Vec.html#method.new
//! [`push`]: ../../std/vec/struct.Vec.html#method.push
//! [`Index`]: ../../std/ops/trait.Index.html
//! [`IndexMut`]: ../../std/ops/trait.IndexMut.html
//! [`vec!`]: ../../std/macro.vec.html
#![stable(feature = "rust1", since = "1.0.0")]
@ -79,7 +86,7 @@ use core::slice;
use super::SpecExtend;
use super::range::RangeArgument;
/// A contiguous growable array type, written `Vec<T>` but pronounced 'vector.'
/// A contiguous growable array type, written `Vec<T>` but pronounced 'vector'.
///
/// # Examples
///
@ -105,7 +112,7 @@ use super::range::RangeArgument;
/// assert_eq!(vec, [7, 1, 2, 3]);
/// ```
///
/// The `vec!` macro is provided to make initialization more convenient:
/// The [`vec!`] macro is provided to make initialization more convenient:
///
/// ```
/// let mut vec = vec![1, 2, 3];
@ -137,19 +144,19 @@ use super::range::RangeArgument;
///
/// # Indexing
///
/// The Vec type allows to access values by index, because it implements the
/// `Index` trait. An example will be more explicit:
/// The `Vec` type allows to access values by index, because it implements the
/// [`Index`] trait. An example will be more explicit:
///
/// ```
/// let v = vec!(0, 2, 4, 6);
/// let v = vec![0, 2, 4, 6];
/// println!("{}", v[1]); // it will display '2'
/// ```
///
/// However be careful: if you try to access an index which isn't in the Vec,
/// However be careful: if you try to access an index which isn't in the `Vec`,
/// your software will panic! You cannot do this:
///
/// ```ignore
/// let v = vec!(0, 2, 4, 6);
/// let v = vec![0, 2, 4, 6];
/// println!("{}", v[6]); // it will panic!
/// ```
///
@ -158,15 +165,15 @@ use super::range::RangeArgument;
///
/// # Slicing
///
/// A Vec can be mutable. Slices, on the other hand, are read-only objects.
/// To get a slice, use "&". Example:
/// A `Vec` can be mutable. Slices, on the other hand, are read-only objects.
/// To get a slice, use `&`. Example:
///
/// ```
/// fn read_slice(slice: &[usize]) {
/// // ...
/// }
///
/// let v = vec!(0, 1);
/// let v = vec![0, 1];
/// read_slice(&v);
///
/// // ... and that's all!
@ -175,8 +182,8 @@ use super::range::RangeArgument;
/// ```
///
/// In Rust, it's more common to pass slices as arguments rather than vectors
/// when you just want to provide a read access. The same goes for String and
/// &str.
/// when you just want to provide a read access. The same goes for [`String`] and
/// [`&str`].
///
/// # Capacity and reallocation
///
@ -191,84 +198,100 @@ use super::range::RangeArgument;
/// with space for 10 more elements. Pushing 10 or fewer elements onto the
/// vector will not change its capacity or cause reallocation to occur. However,
/// if the vector's length is increased to 11, it will have to reallocate, which
/// can be slow. For this reason, it is recommended to use `Vec::with_capacity`
/// can be slow. For this reason, it is recommended to use [`Vec::with_capacity`]
/// whenever possible to specify how big the vector is expected to get.
///
/// # Guarantees
///
/// Due to its incredibly fundamental nature, Vec makes a lot of guarantees
/// Due to its incredibly fundamental nature, `Vec` makes a lot of guarantees
/// about its design. This ensures that it's as low-overhead as possible in
/// the general case, and can be correctly manipulated in primitive ways
/// by unsafe code. Note that these guarantees refer to an unqualified `Vec<T>`.
/// If additional type parameters are added (e.g. to support custom allocators),
/// overriding their defaults may change the behavior.
///
/// Most fundamentally, Vec is and always will be a (pointer, capacity, length)
/// Most fundamentally, `Vec` is and always will be a (pointer, capacity, length)
/// triplet. No more, no less. The order of these fields is completely
/// unspecified, and you should use the appropriate methods to modify these.
/// The pointer will never be null, so this type is null-pointer-optimized.
///
/// However, the pointer may not actually point to allocated memory. In particular,
/// if you construct a Vec with capacity 0 via `Vec::new()`, `vec![]`,
/// `Vec::with_capacity(0)`, or by calling `shrink_to_fit()` on an empty Vec, it
/// will not allocate memory. Similarly, if you store zero-sized types inside
/// a Vec, it will not allocate space for them. *Note that in this case the
/// Vec may not report a `capacity()` of 0*. Vec will allocate if and only
/// if `mem::size_of::<T>() * capacity() > 0`. In general, Vec's allocation
/// if you construct a `Vec` with capacity 0 via [`Vec::new()`], [`vec![]`][`vec!`],
/// [`Vec::with_capacity(0)`][`Vec::with_capacity`], or by calling [`shrink_to_fit()`]
/// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized
/// types inside a `Vec`, it will not allocate space for them. *Note that in this case
/// the `Vec` may not report a [`capacity()`] of 0*. `Vec` will allocate if and only
/// if [`mem::size_of::<T>()`]` * capacity() > 0`. In general, `Vec`'s allocation
/// details are subtle enough that it is strongly recommended that you only
/// free memory allocated by a Vec by creating a new Vec and dropping it.
/// free memory allocated by a `Vec` by creating a new `Vec` and dropping it.
///
/// If a Vec *has* allocated memory, then the memory it points to is on the heap
/// If a `Vec` *has* allocated memory, then the memory it points to is on the heap
/// (as defined by the allocator Rust is configured to use by default), and its
/// pointer points to `len()` initialized elements in order (what you would see
/// if you coerced it to a slice), followed by `capacity() - len()` logically
/// uninitialized elements.
/// pointer points to [`len()`] initialized elements in order (what you would see
/// if you coerced it to a slice), followed by [`capacity()`]` - `[`len()`]
/// logically uninitialized elements.
///
/// Vec will never perform a "small optimization" where elements are actually
/// `Vec` will never perform a "small optimization" where elements are actually
/// stored on the stack for two reasons:
///
/// * It would make it more difficult for unsafe code to correctly manipulate
/// a Vec. The contents of a Vec wouldn't have a stable address if it were
/// only moved, and it would be more difficult to determine if a Vec had
/// a `Vec`. The contents of a `Vec` wouldn't have a stable address if it were
/// only moved, and it would be more difficult to determine if a `Vec` had
/// actually allocated memory.
///
/// * It would penalize the general case, incurring an additional branch
/// on every access.
///
/// Vec will never automatically shrink itself, even if completely empty. This
/// ensures no unnecessary allocations or deallocations occur. Emptying a Vec
/// and then filling it back up to the same `len()` should incur no calls to
/// the allocator. If you wish to free up unused memory, use `shrink_to_fit`.
/// `Vec` will never automatically shrink itself, even if completely empty. This
/// ensures no unnecessary allocations or deallocations occur. Emptying a `Vec`
/// and then filling it back up to the same [`len()`] should incur no calls to
/// the allocator. If you wish to free up unused memory, use
/// [`shrink_to_fit`][`shrink_to_fit()`].
///
/// `push` and `insert` will never (re)allocate if the reported capacity is
/// sufficient. `push` and `insert` *will* (re)allocate if `len() == capacity()`.
/// That is, the reported capacity is completely accurate, and can be relied on.
/// It can even be used to manually free the memory allocated by a Vec if
/// desired. Bulk insertion methods *may* reallocate, even when not necessary.
/// [`push`] and [`insert`] will never (re)allocate if the reported capacity is
/// sufficient. [`push`] and [`insert`] *will* (re)allocate if
/// [`len()`]` == `[`capacity()`]. That is, the reported capacity is completely
/// accurate, and can be relied on. It can even be used to manually free the memory
/// allocated by a `Vec` if desired. Bulk insertion methods *may* reallocate, even
/// when not necessary.
///
/// Vec does not guarantee any particular growth strategy when reallocating
/// when full, nor when `reserve` is called. The current strategy is basic
/// `Vec` does not guarantee any particular growth strategy when reallocating
/// when full, nor when [`reserve`] is called. The current strategy is basic
/// and it may prove desirable to use a non-constant growth factor. Whatever
/// strategy is used will of course guarantee `O(1)` amortized `push`.
/// strategy is used will of course guarantee `O(1)` amortized [`push`].
///
/// `vec![x; n]`, `vec![a, b, c, d]`, and `Vec::with_capacity(n)`, will all
/// produce a Vec with exactly the requested capacity. If `len() == capacity()`,
/// (as is the case for the `vec!` macro), then a `Vec<T>` can be converted
/// to and from a `Box<[T]>` without reallocating or moving the elements.
/// `vec![x; n]`, `vec![a, b, c, d]`, and
/// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec`
/// with exactly the requested capacity. If [`len()`]` == `[`capacity()`],
/// (as is the case for the [`vec!`] macro), then a `Vec<T>` can be converted to
/// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements.
///
/// Vec will not specifically overwrite any data that is removed from it,
/// `Vec` will not specifically overwrite any data that is removed from it,
/// but also won't specifically preserve it. Its uninitialized memory is
/// scratch space that it may use however it wants. It will generally just do
/// whatever is most efficient or otherwise easy to implement. Do not rely on
/// removed data to be erased for security purposes. Even if you drop a Vec, its
/// buffer may simply be reused by another Vec. Even if you zero a Vec's memory
/// removed data to be erased for security purposes. Even if you drop a `Vec`, its
/// buffer may simply be reused by another `Vec`. Even if you zero a `Vec`'s memory
/// first, that may not actually happen because the optimizer does not consider
/// this a side-effect that must be preserved.
///
/// Vec does not currently guarantee the order in which elements are dropped
/// `Vec` does not currently guarantee the order in which elements are dropped
/// (the order has changed in the past, and may change again).
///
#[cfg_attr(stage0, unsafe_no_drop_flag)]
/// [`vec!`]: ../../std/macro.vec.html
/// [`Index`]: ../../std/ops/trait.Index.html
/// [`String`]: ../../std/string/struct.String.html
/// [`&str`]: ../../std/primitive.str.html
/// [`Vec::with_capacity`]: ../../std/vec/struct.Vec.html#method.with_capacity
/// [`Vec::new()`]: ../../std/vec/struct.Vec.html#method.new
/// [`shrink_to_fit()`]: ../../std/vec/struct.Vec.html#method.shrink_to_fit
/// [`capacity()`]: ../../std/vec/struct.Vec.html#method.capacity
/// [`mem::size_of::<T>()`]: ../../std/mem/fn.size_of.html
/// [`len()`]: ../../std/vec/struct.Vec.html#method.len
/// [`push`]: ../../std/vec/struct.Vec.html#method.push
/// [`insert`]: ../../std/vec/struct.Vec.html#method.insert
/// [`reserve`]: ../../std/vec/struct.Vec.html#method.reserve
/// [owned slice]: ../../std/boxed/struct.Box.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Vec<T> {
buf: RawVec<T>,
@ -305,9 +328,10 @@ impl<T> Vec<T> {
/// reallocating. If `capacity` is 0, the vector will not allocate.
///
/// It is important to note that this function does not specify the *length*
/// of the returned vector, but only the *capacity*. (For an explanation of
/// the difference between length and capacity, see the main `Vec<T>` docs
/// above, 'Capacity and reallocation'.)
/// of the returned vector, but only the *capacity*. For an explanation of
/// the difference between length and capacity, see *[Capacity and reallocation]*.
///
/// [Capacity and reallocation]: #capacity-and-reallocation
///
/// # Examples
///
@ -341,7 +365,7 @@ impl<T> Vec<T> {
/// This is highly unsafe, due to the number of invariants that aren't
/// checked:
///
/// * `ptr` needs to have been previously allocated via `String`/`Vec<T>`
/// * `ptr` needs to have been previously allocated via [`String`]/`Vec<T>`
/// (at least, it's highly likely to be incorrect if it wasn't).
/// * `length` needs to be less than or equal to `capacity`.
/// * `capacity` needs to be the capacity that the pointer was allocated with.
@ -355,6 +379,8 @@ impl<T> Vec<T> {
/// that nothing else uses the pointer after calling this
/// function.
///
/// [`String`]: ../../std/string/struct.String.html
///
/// # Examples
///
/// ```
@ -471,11 +497,15 @@ impl<T> Vec<T> {
self.buf.shrink_to_fit(self.len);
}
/// Converts the vector into Box<[T]>.
/// Converts the vector into [`Box<[T]>`][owned slice].
///
/// Note that this will drop any excess capacity. Calling this and
/// converting back to a vector with `into_vec()` is equivalent to calling
/// `shrink_to_fit()`.
/// converting back to a vector with [`into_vec()`] is equivalent to calling
/// [`shrink_to_fit()`].
///
/// [owned slice]: ../../std/boxed/struct.Box.html
/// [`into_vec()`]: ../../std/primitive.slice.html#method.into_vec
/// [`shrink_to_fit()`]: #method.shrink_to_fit
///
/// # Examples
///
@ -674,7 +704,7 @@ impl<T> Vec<T> {
///
/// # Panics
///
/// Panics if `index` is greater than the vector's length.
/// Panics if `index` is out of bounds.
///
/// # Examples
///
@ -749,7 +779,7 @@ impl<T> Vec<T> {
/// Retains only the elements specified by the predicate.
///
/// In other words, remove all elements `e` such that `f(&e)` returns false.
/// In other words, remove all elements `e` such that `f(&e)` returns `false`.
/// This method operates in place and preserves the order of the retained
/// elements.
///
@ -782,6 +812,130 @@ impl<T> Vec<T> {
}
}
/// Removes consecutive elements in the vector that resolve to the same key.
///
/// If the vector is sorted, this removes all duplicates.
///
/// # Examples
///
/// ```
/// #![feature(dedup_by)]
///
/// let mut vec = vec![10, 20, 21, 30, 20];
///
/// vec.dedup_by_key(|i| *i / 10);
///
/// assert_eq!(vec, [10, 20, 30, 20]);
/// ```
#[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")]
#[inline]
pub fn dedup_by_key<F, K>(&mut self, mut key: F) where F: FnMut(&mut T) -> K, K: PartialEq {
self.dedup_by(|a, b| key(a) == key(b))
}
/// Removes consecutive elements in the vector that resolve to the same key.
///
/// If the vector is sorted, this removes all duplicates.
///
/// # Examples
///
/// ```
/// #![feature(dedup_by)]
/// use std::ascii::AsciiExt;
///
/// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
///
/// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
///
/// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
/// ```
#[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")]
pub fn dedup_by<F>(&mut self, mut same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {
unsafe {
// Although we have a mutable reference to `self`, we cannot make
// *arbitrary* changes. The `same_bucket` calls could panic, so we
// must ensure that the vector is in a valid state at all time.
//
// The way that we handle this is by using swaps; we iterate
// over all the elements, swapping as we go so that at the end
// the elements we wish to keep are in the front, and those we
// wish to reject are at the back. We can then truncate the
// vector. This operation is still O(n).
//
// Example: We start in this state, where `r` represents "next
// read" and `w` represents "next_write`.
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 1 | 2 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Comparing self[r] against self[w-1], this is not a duplicate, so
// we swap self[r] and self[w] (no effect as r==w) and then increment both
// r and w, leaving us with:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 1 | 2 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Comparing self[r] against self[w-1], this value is a duplicate,
// so we increment `r` but leave everything else unchanged:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 1 | 2 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Comparing self[r] against self[w-1], this is not a duplicate,
// so swap self[r] and self[w] and advance r and w:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 2 | 1 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Not a duplicate, repeat:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 2 | 3 | 1 | 3 |
// +---+---+---+---+---+---+
// w
//
// Duplicate, advance r. End of vec. Truncate to w.
let ln = self.len();
if ln <= 1 {
return;
}
// Avoid bounds checks by using raw pointers.
let p = self.as_mut_ptr();
let mut r: usize = 1;
let mut w: usize = 1;
while r < ln {
let p_r = p.offset(r as isize);
let p_wm1 = p.offset((w - 1) as isize);
if !same_bucket(&mut *p_r, &mut *p_wm1) {
if r != w {
let p_w = p_wm1.offset(1);
mem::swap(&mut *p_r, &mut *p_w);
}
w += 1;
}
r += 1;
}
self.truncate(w);
}
}
/// Appends an element to the back of a collection.
///
/// # Panics
@ -810,9 +964,11 @@ impl<T> Vec<T> {
}
}
/// Removes the last element from a vector and returns it, or `None` if it
/// Removes the last element from a vector and returns it, or [`None`] if it
/// is empty.
///
/// [`None`]: ../../std/option/enum.Option.html#variant.None
///
/// # Examples
///
/// ```
@ -1156,90 +1312,9 @@ impl<T: PartialEq> Vec<T> {
/// assert_eq!(vec, [1, 2, 3, 2]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn dedup(&mut self) {
unsafe {
// Although we have a mutable reference to `self`, we cannot make
// *arbitrary* changes. The `PartialEq` comparisons could panic, so we
// must ensure that the vector is in a valid state at all time.
//
// The way that we handle this is by using swaps; we iterate
// over all the elements, swapping as we go so that at the end
// the elements we wish to keep are in the front, and those we
// wish to reject are at the back. We can then truncate the
// vector. This operation is still O(n).
//
// Example: We start in this state, where `r` represents "next
// read" and `w` represents "next_write`.
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 1 | 2 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Comparing self[r] against self[w-1], this is not a duplicate, so
// we swap self[r] and self[w] (no effect as r==w) and then increment both
// r and w, leaving us with:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 1 | 2 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Comparing self[r] against self[w-1], this value is a duplicate,
// so we increment `r` but leave everything else unchanged:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 1 | 2 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Comparing self[r] against self[w-1], this is not a duplicate,
// so swap self[r] and self[w] and advance r and w:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 2 | 1 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Not a duplicate, repeat:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 2 | 3 | 1 | 3 |
// +---+---+---+---+---+---+
// w
//
// Duplicate, advance r. End of vec. Truncate to w.
let ln = self.len();
if ln <= 1 {
return;
}
// Avoid bounds checks by using raw pointers.
let p = self.as_mut_ptr();
let mut r: usize = 1;
let mut w: usize = 1;
while r < ln {
let p_r = p.offset(r as isize);
let p_wm1 = p.offset((w - 1) as isize);
if *p_r != *p_wm1 {
if r != w {
let p_w = p_wm1.offset(1);
mem::swap(&mut *p_r, &mut *p_w);
}
w += 1;
}
r += 1;
}
self.truncate(w);
}
self.dedup_by(|a, b| a == b)
}
}
@ -1572,7 +1647,24 @@ impl<T> Vec<T> {
#[stable(feature = "extend_ref", since = "1.2.0")]
impl<'a, T: 'a + Copy> Extend<&'a T> for Vec<T> {
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
self.extend(iter.into_iter().cloned());
<I as SpecExtendVec<T>>::extend_vec(iter, self);
}
}
// helper trait for specialization of Vec's Extend impl
trait SpecExtendVec<T> {
fn extend_vec(self, vec: &mut Vec<T>);
}
impl <'a, T: 'a + Copy, I: IntoIterator<Item=&'a T>> SpecExtendVec<T> for I {
default fn extend_vec(self, vec: &mut Vec<T>) {
vec.extend(self.into_iter().cloned());
}
}
impl<'a, T: Copy> SpecExtendVec<T> for &'a [T] {
fn extend_vec(self, vec: &mut Vec<T>) {
vec.extend_from_slice(self);
}
}
@ -1705,6 +1797,13 @@ impl<'a, T: Clone> From<&'a [T]> for Vec<T> {
}
}
#[stable(feature = "vec_from_cow_slice", since = "1.14.0")]
impl<'a, T> From<Cow<'a, [T]>> for Vec<T> where [T]: ToOwned<Owned=Vec<T>> {
fn from(s: Cow<'a, [T]>) -> Vec<T> {
s.into_owned()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> From<&'a str> for Vec<u8> {
fn from(s: &'a str) -> Vec<u8> {
@ -1756,7 +1855,7 @@ pub struct IntoIter<T> {
end: *const T,
}
#[stable(feature = "vec_intoiter_debug", since = "")]
#[stable(feature = "vec_intoiter_debug", since = "1.13.0")]
impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("IntoIter")
@ -1770,7 +1869,7 @@ impl<T> IntoIter<T> {
///
/// # Examples
///
/// ```rust
/// ```
/// # #![feature(vec_into_iter_as_slice)]
/// let vec = vec!['a', 'b', 'c'];
/// let mut into_iter = vec.into_iter();
@ -1789,7 +1888,7 @@ impl<T> IntoIter<T> {
///
/// # Examples
///
/// ```rust
/// ```
/// # #![feature(vec_into_iter_as_slice)]
/// let vec = vec!['a', 'b', 'c'];
/// let mut into_iter = vec.into_iter();
@ -1930,7 +2029,7 @@ unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {}
#[stable(feature = "drain", since = "1.6.0")]
unsafe impl<'a, T: Send> Send for Drain<'a, T> {}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "drain", since = "1.6.0")]
impl<'a, T> Iterator for Drain<'a, T> {
type Item = T;
@ -1944,7 +2043,7 @@ impl<'a, T> Iterator for Drain<'a, T> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "drain", since = "1.6.0")]
impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<T> {
@ -1952,7 +2051,7 @@ impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "drain", since = "1.6.0")]
impl<'a, T> Drop for Drain<'a, T> {
fn drop(&mut self) {
// exhaust self first
@ -1974,7 +2073,7 @@ impl<'a, T> Drop for Drain<'a, T> {
}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "drain", since = "1.6.0")]
impl<'a, T> ExactSizeIterator for Drain<'a, T> {}
#[unstable(feature = "fused", issue = "35602")]

View file

@ -726,33 +726,25 @@ impl<T> VecDeque<T> {
/// ```
/// use std::collections::VecDeque;
///
/// let mut vector: VecDeque<u32> = VecDeque::new();
/// let mut vector = VecDeque::new();
///
/// vector.push_back(0);
/// vector.push_back(1);
/// vector.push_back(2);
///
/// assert_eq!(vector.as_slices(), (&[0u32, 1, 2] as &[u32], &[] as &[u32]));
/// assert_eq!(vector.as_slices(), (&[0, 1, 2][..], &[][..]));
///
/// vector.push_front(10);
/// vector.push_front(9);
///
/// assert_eq!(vector.as_slices(), (&[9u32, 10] as &[u32], &[0u32, 1, 2] as &[u32]));
/// assert_eq!(vector.as_slices(), (&[9, 10][..], &[0, 1, 2][..]));
/// ```
#[inline]
#[stable(feature = "deque_extras_15", since = "1.5.0")]
pub fn as_slices(&self) -> (&[T], &[T]) {
unsafe {
let contiguous = self.is_contiguous();
let buf = self.buffer_as_slice();
if contiguous {
let (empty, buf) = buf.split_at(0);
(&buf[self.tail..self.head], empty)
} else {
let (mid, right) = buf.split_at(self.tail);
let (left, _) = mid.split_at(self.head);
(right, left)
}
RingSlices::ring_slices(buf, self.head, self.tail)
}
}
@ -764,7 +756,7 @@ impl<T> VecDeque<T> {
/// ```
/// use std::collections::VecDeque;
///
/// let mut vector: VecDeque<u32> = VecDeque::new();
/// let mut vector = VecDeque::new();
///
/// vector.push_back(0);
/// vector.push_back(1);
@ -774,26 +766,16 @@ impl<T> VecDeque<T> {
///
/// vector.as_mut_slices().0[0] = 42;
/// vector.as_mut_slices().1[0] = 24;
/// assert_eq!(vector.as_slices(), (&[42u32, 10] as &[u32], &[24u32, 1] as &[u32]));
/// assert_eq!(vector.as_slices(), (&[42, 10][..], &[24, 1][..]));
/// ```
#[inline]
#[stable(feature = "deque_extras_15", since = "1.5.0")]
pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
unsafe {
let contiguous = self.is_contiguous();
let head = self.head;
let tail = self.tail;
let buf = self.buffer_as_mut_slice();
if contiguous {
let (empty, buf) = buf.split_at_mut(0);
(&mut buf[tail..head], empty)
} else {
let (mid, right) = buf.split_at_mut(tail);
let (left, _) = mid.split_at_mut(head);
(right, left)
}
RingSlices::ring_slices(buf, head, tail)
}
}
@ -1829,6 +1811,42 @@ fn wrap_index(index: usize, size: usize) -> usize {
index & (size - 1)
}
/// Returns the two slices that cover the VecDeque's valid range
trait RingSlices : Sized {
fn slice(self, from: usize, to: usize) -> Self;
fn split_at(self, i: usize) -> (Self, Self);
fn ring_slices(buf: Self, head: usize, tail: usize) -> (Self, Self) {
let contiguous = tail <= head;
if contiguous {
let (empty, buf) = buf.split_at(0);
(buf.slice(tail, head), empty)
} else {
let (mid, right) = buf.split_at(tail);
let (left, _) = mid.split_at(head);
(right, left)
}
}
}
impl<'a, T> RingSlices for &'a [T] {
fn slice(self, from: usize, to: usize) -> Self {
&self[from..to]
}
fn split_at(self, i: usize) -> (Self, Self) {
(*self).split_at(i)
}
}
impl<'a, T> RingSlices for &'a mut [T] {
fn slice(self, from: usize, to: usize) -> Self {
&mut self[from..to]
}
fn split_at(self, i: usize) -> (Self, Self) {
(*self).split_at_mut(i)
}
}
/// Calculate the number of elements left to be read in the buffer
#[inline]
fn count(tail: usize, head: usize, size: usize) -> usize {
@ -1875,6 +1893,14 @@ impl<'a, T> Iterator for Iter<'a, T> {
let len = count(self.tail, self.head, self.ring.len());
(len, Some(len))
}
fn fold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
where F: FnMut(Acc, Self::Item) -> Acc,
{
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
accum = front.iter().fold(accum, &mut f);
back.iter().fold(accum, &mut f)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -1927,6 +1953,14 @@ impl<'a, T> Iterator for IterMut<'a, T> {
let len = count(self.tail, self.head, self.ring.len());
(len, Some(len))
}
fn fold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
where F: FnMut(Acc, Self::Item) -> Acc,
{
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
accum = front.iter_mut().fold(accum, &mut f);
back.iter_mut().fold(accum, &mut f)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -2002,7 +2036,7 @@ unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {}
#[stable(feature = "drain", since = "1.6.0")]
unsafe impl<'a, T: Send> Send for Drain<'a, T> {}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "drain", since = "1.6.0")]
impl<'a, T: 'a> Drop for Drain<'a, T> {
fn drop(&mut self) {
for _ in self.by_ref() {}
@ -2051,7 +2085,7 @@ impl<'a, T: 'a> Drop for Drain<'a, T> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "drain", since = "1.6.0")]
impl<'a, T: 'a> Iterator for Drain<'a, T> {
type Item = T;
@ -2066,7 +2100,7 @@ impl<'a, T: 'a> Iterator for Drain<'a, T> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "drain", since = "1.6.0")]
impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<T> {
@ -2074,7 +2108,7 @@ impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "drain", since = "1.6.0")]
impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
#[unstable(feature = "fused", issue = "35602")]

View file

@ -139,6 +139,7 @@ fn test_push_unique() {
}
#[test]
#[allow(deprecated)]
fn test_push_pop() {
let mut heap = BinaryHeap::from(vec![5, 5, 2, 1, 3]);
assert_eq!(heap.len(), 5);
@ -153,6 +154,7 @@ fn test_push_pop() {
}
#[test]
#[allow(deprecated)]
fn test_replace() {
let mut heap = BinaryHeap::from(vec![5, 5, 2, 1, 3]);
assert_eq!(heap.len(), 5);
@ -212,6 +214,7 @@ fn test_empty_peek_mut() {
}
#[test]
#[allow(deprecated)]
fn test_empty_replace() {
let mut heap = BinaryHeap::new();
assert!(heap.replace(5).is_none());
@ -296,5 +299,7 @@ fn test_extend_specialization() {
#[allow(dead_code)]
fn assert_covariance() {
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d }
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
d
}
}

View file

@ -533,9 +533,7 @@ create_append_test!(test_append_1700, 1700);
fn rand_data(len: usize) -> Vec<(u32, u32)> {
let mut rng = DeterministicRng::new();
Vec::from_iter(
(0..len).map(|_| (rng.next(), rng.next()))
)
Vec::from_iter((0..len).map(|_| (rng.next(), rng.next())))
}
#[test]

View file

@ -25,7 +25,7 @@ impl DeterministicRng {
x: 0x193a6754,
y: 0xa8a7d469,
z: 0x97830e05,
w: 0x113ba7bb
w: 0x113ba7bb,
}
}

View file

@ -15,45 +15,51 @@ use super::DeterministicRng;
#[test]
fn test_clone_eq() {
let mut m = BTreeSet::new();
let mut m = BTreeSet::new();
m.insert(1);
m.insert(2);
m.insert(1);
m.insert(2);
assert!(m.clone() == m);
assert!(m.clone() == m);
}
#[test]
fn test_hash() {
let mut x = BTreeSet::new();
let mut y = BTreeSet::new();
let mut x = BTreeSet::new();
let mut y = BTreeSet::new();
x.insert(1);
x.insert(2);
x.insert(3);
x.insert(1);
x.insert(2);
x.insert(3);
y.insert(3);
y.insert(2);
y.insert(1);
y.insert(3);
y.insert(2);
y.insert(1);
assert!(::hash(&x) == ::hash(&y));
assert!(::hash(&x) == ::hash(&y));
}
fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F) where
F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, &mut FnMut(&i32) -> bool) -> bool,
fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F)
where F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, &mut FnMut(&i32) -> bool) -> bool
{
let mut set_a = BTreeSet::new();
let mut set_b = BTreeSet::new();
for x in a { assert!(set_a.insert(*x)) }
for y in b { assert!(set_b.insert(*y)) }
for x in a {
assert!(set_a.insert(*x))
}
for y in b {
assert!(set_b.insert(*y))
}
let mut i = 0;
f(&set_a, &set_b, &mut |&x| {
assert_eq!(x, expected[i]);
i += 1;
true
});
f(&set_a,
&set_b,
&mut |&x| {
assert_eq!(x, expected[i]);
i += 1;
true
});
assert_eq!(i, expected.len());
}
@ -82,9 +88,7 @@ fn test_difference() {
check_difference(&[], &[], &[]);
check_difference(&[1, 12], &[], &[1, 12]);
check_difference(&[], &[1, 2, 3, 9], &[]);
check_difference(&[1, 3, 5, 9, 11],
&[3, 9],
&[1, 5, 11]);
check_difference(&[1, 3, 5, 9, 11], &[3, 9], &[1, 5, 11]);
check_difference(&[-5, 11, 22, 33, 40, 42],
&[-12, -5, 14, 23, 34, 38, 39, 50],
&[11, 22, 33, 40, 42]);
@ -245,10 +249,18 @@ fn test_recovery() {
fn test_variance() {
use std::collections::btree_set::{IntoIter, Iter, Range};
fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> { v }
fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> { v }
fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> { v }
fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> { v }
fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> {
v
}
fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> {
v
}
fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> {
v
}
fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> {
v
}
}
#[test]
@ -277,9 +289,7 @@ fn test_append() {
fn rand_data(len: usize) -> Vec<u32> {
let mut rng = DeterministicRng::new();
Vec::from_iter(
(0..len).map(|_| rng.next())
)
Vec::from_iter((0..len).map(|_| rng.next()))
}
#[test]

View file

@ -0,0 +1,65 @@
// Copyright 2012-2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::borrow::Cow;
// check that Cow<'a, str> implements addition
#[test]
fn check_cow_add() {
borrowed1 = Cow::Borrowed("Hello, ");
borrowed2 = Cow::Borrowed("World!");
borrow_empty = Cow::Borrowed("");
owned1 = Cow::Owned("Hi, ".into());
owned2 = Cow::Owned("Rustaceans!".into());
owned_empty = Cow::Owned("".into());
assert_eq!("Hello, World!", borrowed1 + borrowed2);
assert_eq!("Hello, Rustaceans!", borrowed1 + owned2);
assert_eq!("Hello, World!", owned1 + borrowed2);
assert_eq!("Hello, Rustaceans!", owned1 + owned2);
if let Cow::Owned(_) = borrowed1 + borrow_empty {
panic!("Adding empty strings to a borrow should note allocate");
}
if let Cow::Owned(_) = borrow_empty + borrowed1 {
panic!("Adding empty strings to a borrow should note allocate");
}
if let Cow::Owned(_) = borrowed1 + owned_empty {
panic!("Adding empty strings to a borrow should note allocate");
}
if let Cow::Owned(_) = owned_empty + borrowed1 {
panic!("Adding empty strings to a borrow should note allocate");
}
}
fn check_cow_add_assign() {
borrowed1 = Cow::Borrowed("Hello, ");
borrowed2 = Cow::Borrowed("World!");
borrow_empty = Cow::Borrowed("");
owned1 = Cow::Owned("Hi, ".into());
owned2 = Cow::Owned("Rustaceans!".into());
owned_empty = Cow::Owned("".into());
let borrowed1clone = borrowed1.clone();
borrowed1clone += borrow_empty;
assert_eq!((&borrowed1clone).as_ptr(), (&borrowed1).as_ptr());
borrowed1clone += owned_empty;
assert_eq!((&borrowed1clone).as_ptr(), (&borrowed1).as_ptr());
owned1 += borrowed2;
borrowed1 += owned2;
assert_eq!("Hello, World!", owned1);
assert_eq!("Hello, Rustaceans!", borrowed1);
}

View file

@ -16,9 +16,11 @@
#![feature(collections)]
#![feature(collections_bound)]
#![feature(const_fn)]
#![feature(dedup_by)]
#![feature(enumset)]
#![feature(pattern)]
#![feature(rand)]
#![feature(repeat_str)]
#![feature(step_by)]
#![feature(str_escape)]
#![feature(str_replacen)]
@ -31,9 +33,12 @@ extern crate collections;
extern crate test;
extern crate rustc_unicode;
use std::hash::{Hash, Hasher, SipHasher};
use std::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;
#[cfg(test)] #[macro_use] mod bench;
#[cfg(test)]
#[macro_use]
mod bench;
mod binary_heap;
mod btree;
@ -47,7 +52,7 @@ mod vec_deque;
mod vec;
fn hash<T: Hash>(t: &T) -> u64 {
let mut s = SipHasher::new();
let mut s = DefaultHasher::new();
t.hash(&mut s);
s.finish()
}

View file

@ -315,47 +315,6 @@ fn test_clear() {
// If the unsafe block didn't drop things properly, we blow up here.
}
#[test]
fn test_dedup() {
fn case(a: Vec<i32>, b: Vec<i32>) {
let mut v = a;
v.dedup();
assert_eq!(v, b);
}
case(vec![], vec![]);
case(vec![1], vec![1]);
case(vec![1, 1], vec![1]);
case(vec![1, 2, 3], vec![1, 2, 3]);
case(vec![1, 1, 2, 3], vec![1, 2, 3]);
case(vec![1, 2, 2, 3], vec![1, 2, 3]);
case(vec![1, 2, 3, 3], vec![1, 2, 3]);
case(vec![1, 1, 2, 2, 2, 3, 3], vec![1, 2, 3]);
}
#[test]
fn test_dedup_unique() {
let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];
v0.dedup();
let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3];
v1.dedup();
let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3];
v2.dedup();
// If the boxed pointers were leaked or otherwise misused, valgrind
// and/or rt should raise errors.
}
#[test]
fn test_dedup_shared() {
let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];
v0.dedup();
let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3];
v1.dedup();
let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3];
v2.dedup();
// If the pointers were leaked or otherwise misused, valgrind and/or
// rt should raise errors.
}
#[test]
fn test_retain() {
let mut v = vec![1, 2, 3, 4, 5];
@ -461,12 +420,12 @@ fn test_sort_stability() {
// number this element is, i.e. the second elements
// will occur in sorted order.
let mut v: Vec<_> = (0..len)
.map(|_| {
let n = thread_rng().gen::<usize>() % 10;
counts[n] += 1;
(n, counts[n])
})
.collect();
.map(|_| {
let n = thread_rng().gen::<usize>() % 10;
counts[n] += 1;
(n, counts[n])
})
.collect();
// only sort on the first element, so an unstable sort
// may mix up the counts.
@ -1116,6 +1075,7 @@ fn test_box_slice_clone() {
}
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
fn test_box_slice_clone_panics() {
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
@ -1156,13 +1116,13 @@ fn test_box_slice_clone_panics() {
};
spawn(move || {
// When xs is dropped, +5.
let xs = vec![canary.clone(), canary.clone(), canary.clone(), panic, canary]
.into_boxed_slice();
// When xs is dropped, +5.
let xs = vec![canary.clone(), canary.clone(), canary.clone(), panic, canary]
.into_boxed_slice();
// When panic is cloned, +3.
xs.clone();
})
// When panic is cloned, +3.
xs.clone();
})
.join()
.unwrap_err();
@ -1414,8 +1374,8 @@ mod bench {
let mut rng = thread_rng();
b.iter(|| {
let mut v = rng.gen_iter::<BigSortable>()
.take(5)
.collect::<Vec<BigSortable>>();
.take(5)
.collect::<Vec<BigSortable>>();
v.sort();
});
b.bytes = 5 * mem::size_of::<BigSortable>() as u64;
@ -1426,8 +1386,8 @@ mod bench {
let mut rng = thread_rng();
b.iter(|| {
let mut v = rng.gen_iter::<BigSortable>()
.take(100)
.collect::<Vec<BigSortable>>();
.take(100)
.collect::<Vec<BigSortable>>();
v.sort();
});
b.bytes = 100 * mem::size_of::<BigSortable>() as u64;
@ -1438,8 +1398,8 @@ mod bench {
let mut rng = thread_rng();
b.iter(|| {
let mut v = rng.gen_iter::<BigSortable>()
.take(10000)
.collect::<Vec<BigSortable>>();
.take(10000)
.collect::<Vec<BigSortable>>();
v.sort();
});
b.bytes = 10000 * mem::size_of::<BigSortable>() as u64;

View file

@ -786,9 +786,9 @@ fn test_rev_iterator() {
#[test]
fn test_chars_decoding() {
let mut bytes = [0; 4];
for c in (0..0x110000).filter_map(::std::char::from_u32) {
let bytes = c.encode_utf8();
let s = ::std::str::from_utf8(bytes.as_slice()).unwrap();
let s = c.encode_utf8(&mut bytes);
if Some(c) != s.chars().next() {
panic!("character {:x}={} does not decode correctly", c as u32, c);
}
@ -797,9 +797,9 @@ fn test_chars_decoding() {
#[test]
fn test_chars_rev_decoding() {
let mut bytes = [0; 4];
for c in (0..0x110000).filter_map(::std::char::from_u32) {
let bytes = c.encode_utf8();
let s = ::std::str::from_utf8(bytes.as_slice()).unwrap();
let s = c.encode_utf8(&mut bytes);
if Some(c) != s.chars().rev().next() {
panic!("character {:x}={} does not decode correctly", c as u32, c);
}
@ -1286,6 +1286,13 @@ fn test_cow_from() {
}
}
#[test]
fn test_repeat() {
assert_eq!("".repeat(3), "");
assert_eq!("abc".repeat(0), "");
assert_eq!("α".repeat(3), "ααα");
}
mod pattern {
use std::str::pattern::Pattern;
use std::str::pattern::{Searcher, ReverseSearcher};

View file

@ -35,6 +35,12 @@ fn test_from_str() {
assert_eq!(owned.as_ref().map(|s| &**s), Some("string"));
}
#[test]
fn test_from_cow_str() {
assert_eq!(String::from(Cow::Borrowed("string")), "string");
assert_eq!(String::from(Cow::Owned(String::from("string"))), "string");
}
#[test]
fn test_unsized_to_string() {
let s: &str = "abc";

View file

@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::iter::{FromIterator, repeat};
use std::mem::size_of;
@ -213,6 +214,60 @@ fn test_retain() {
assert_eq!(vec, [2, 4]);
}
#[test]
fn test_dedup() {
fn case(a: Vec<i32>, b: Vec<i32>) {
let mut v = a;
v.dedup();
assert_eq!(v, b);
}
case(vec![], vec![]);
case(vec![1], vec![1]);
case(vec![1, 1], vec![1]);
case(vec![1, 2, 3], vec![1, 2, 3]);
case(vec![1, 1, 2, 3], vec![1, 2, 3]);
case(vec![1, 2, 2, 3], vec![1, 2, 3]);
case(vec![1, 2, 3, 3], vec![1, 2, 3]);
case(vec![1, 1, 2, 2, 2, 3, 3], vec![1, 2, 3]);
}
#[test]
fn test_dedup_by_key() {
fn case(a: Vec<i32>, b: Vec<i32>) {
let mut v = a;
v.dedup_by_key(|i| *i / 10);
assert_eq!(v, b);
}
case(vec![], vec![]);
case(vec![10], vec![10]);
case(vec![10, 11], vec![10]);
case(vec![10, 20, 30], vec![10, 20, 30]);
case(vec![10, 11, 20, 30], vec![10, 20, 30]);
case(vec![10, 20, 21, 30], vec![10, 20, 30]);
case(vec![10, 20, 30, 31], vec![10, 20, 30]);
case(vec![10, 11, 20, 21, 22, 30, 31], vec![10, 20, 30]);
}
#[test]
fn test_dedup_by() {
let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
}
#[test]
fn test_dedup_unique() {
let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];
v0.dedup();
let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3];
v1.dedup();
let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3];
v2.dedup();
// If the boxed pointers were leaked or otherwise misused, valgrind
// and/or rt should raise errors.
}
#[test]
fn zero_sized_values() {
let mut v = Vec::new();
@ -271,22 +326,22 @@ fn test_zip_unzip() {
#[test]
fn test_vec_truncate_drop() {
static mut drops: u32 = 0;
static mut DROPS: u32 = 0;
struct Elem(i32);
impl Drop for Elem {
fn drop(&mut self) {
unsafe {
drops += 1;
DROPS += 1;
}
}
}
let mut v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)];
assert_eq!(unsafe { drops }, 0);
assert_eq!(unsafe { DROPS }, 0);
v.truncate(3);
assert_eq!(unsafe { drops }, 2);
assert_eq!(unsafe { DROPS }, 2);
v.truncate(0);
assert_eq!(unsafe { drops }, 5);
assert_eq!(unsafe { DROPS }, 5);
}
#[test]
@ -542,10 +597,22 @@ fn test_cow_from() {
}
}
#[test]
fn test_from_cow() {
let borrowed: &[_] = &["borrowed", "(slice)"];
let owned = vec!["owned", "(vec)"];
assert_eq!(Vec::from(Cow::Borrowed(borrowed)), vec!["borrowed", "(slice)"]);
assert_eq!(Vec::from(Cow::Owned(owned)), vec!["owned", "(vec)"]);
}
#[allow(dead_code)]
fn assert_covariance() {
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d }
fn into_iter<'new>(i: IntoIter<&'static str>) -> IntoIter<&'new str> { i }
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
d
}
fn into_iter<'new>(i: IntoIter<&'static str>) -> IntoIter<&'new str> {
i
}
}
#[bench]

View file

@ -686,21 +686,21 @@ fn test_show() {
assert_eq!(format!("{:?}", ringbuf), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"]
.iter()
.cloned()
.collect();
.iter()
.cloned()
.collect();
assert_eq!(format!("{:?}", ringbuf),
"[\"just\", \"one\", \"test\", \"more\"]");
}
#[test]
fn test_drop() {
static mut drops: i32 = 0;
static mut DROPS: i32 = 0;
struct Elem;
impl Drop for Elem {
fn drop(&mut self) {
unsafe {
drops += 1;
DROPS += 1;
}
}
}
@ -712,17 +712,17 @@ fn test_drop() {
ring.push_front(Elem);
drop(ring);
assert_eq!(unsafe { drops }, 4);
assert_eq!(unsafe { DROPS }, 4);
}
#[test]
fn test_drop_with_pop() {
static mut drops: i32 = 0;
static mut DROPS: i32 = 0;
struct Elem;
impl Drop for Elem {
fn drop(&mut self) {
unsafe {
drops += 1;
DROPS += 1;
}
}
}
@ -735,20 +735,20 @@ fn test_drop_with_pop() {
drop(ring.pop_back());
drop(ring.pop_front());
assert_eq!(unsafe { drops }, 2);
assert_eq!(unsafe { DROPS }, 2);
drop(ring);
assert_eq!(unsafe { drops }, 4);
assert_eq!(unsafe { DROPS }, 4);
}
#[test]
fn test_drop_clear() {
static mut drops: i32 = 0;
static mut DROPS: i32 = 0;
struct Elem;
impl Drop for Elem {
fn drop(&mut self) {
unsafe {
drops += 1;
DROPS += 1;
}
}
}
@ -759,10 +759,10 @@ fn test_drop_clear() {
ring.push_back(Elem);
ring.push_front(Elem);
ring.clear();
assert_eq!(unsafe { drops }, 4);
assert_eq!(unsafe { DROPS }, 4);
drop(ring);
assert_eq!(unsafe { drops }, 4);
assert_eq!(unsafe { DROPS }, 4);
}
#[test]
@ -1003,5 +1003,7 @@ fn test_contains() {
#[allow(dead_code)]
fn assert_covariance() {
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d }
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
d
}
}

View file

@ -72,7 +72,13 @@ impl Sources {
}
fn main() {
let target = env::var("TARGET").unwrap();
let target = env::var("TARGET").expect("TARGET was not set");
// Emscripten's runtime includes all the builtins
if target.contains("emscripten") {
return;
}
let cfg = &mut gcc::Config::new();
if target.contains("msvc") {

View file

@ -8,9 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![cfg_attr(not(stage0), feature(compiler_builtins))]
#![feature(compiler_builtins)]
#![no_std]
#![cfg_attr(not(stage0), compiler_builtins)]
#![compiler_builtins]
#![unstable(feature = "compiler_builtins_lib",
reason = "internal implementation detail of rustc right now",
issue = "0")]

View file

@ -73,7 +73,6 @@
use fmt;
use intrinsics;
use marker::Reflect;
///////////////////////////////////////////////////////////////////////////////
// Any trait
@ -86,7 +85,7 @@ use marker::Reflect;
///
/// [mod]: index.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Any: Reflect + 'static {
pub trait Any: 'static {
/// Gets the `TypeId` of `self`.
///
/// # Examples
@ -112,7 +111,7 @@ pub trait Any: Reflect + 'static {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Reflect + 'static + ?Sized > Any for T {
impl<T: 'static + ?Sized > Any for T {
fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
}
@ -352,12 +351,10 @@ impl TypeId {
/// # Examples
///
/// ```
/// #![feature(get_type_id)]
///
/// use std::any::{Any, TypeId};
///
/// fn is_string(s: &Any) -> bool {
/// TypeId::of::<String>() == s.get_type_id()
/// fn is_string<T: ?Sized + Any>(_s: &T) -> bool {
/// TypeId::of::<String>() == TypeId::of::<T>()
/// }
///
/// fn main() {
@ -366,7 +363,7 @@ impl TypeId {
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn of<T: ?Sized + Reflect + 'static>() -> TypeId {
pub fn of<T: ?Sized + 'static>() -> TypeId {
TypeId {
t: unsafe { intrinsics::type_id::<T>() },
}

View file

@ -93,6 +93,7 @@ macro_rules! __impl_slice_eq2 {
macro_rules! array_impls {
($($N:expr)+) => {
$(
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> AsRef<[T]> for [T; $N] {
#[inline]
fn as_ref(&self) -> &[T] {
@ -100,6 +101,7 @@ macro_rules! array_impls {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> AsMut<[T]> for [T; $N] {
#[inline]
fn as_mut(&mut self) -> &mut [T] {

View file

@ -175,7 +175,7 @@
use cmp::Ordering;
use fmt::{self, Debug, Display};
use marker::{PhantomData, Unsize};
use marker::Unsize;
use ops::{Deref, DerefMut, CoerceUnsized};
/// A mutable memory location that admits only `Copy` data.
@ -403,40 +403,40 @@ pub enum BorrowState {
}
/// An error returned by [`RefCell::try_borrow`](struct.RefCell.html#method.try_borrow).
#[unstable(feature = "try_borrow", issue = "35070")]
pub struct BorrowError<'a, T: 'a + ?Sized> {
marker: PhantomData<&'a RefCell<T>>,
#[stable(feature = "try_borrow", since = "1.13.0")]
pub struct BorrowError {
_private: (),
}
#[unstable(feature = "try_borrow", issue = "35070")]
impl<'a, T: ?Sized> Debug for BorrowError<'a, T> {
#[stable(feature = "try_borrow", since = "1.13.0")]
impl Debug for BorrowError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("BorrowError").finish()
}
}
#[unstable(feature = "try_borrow", issue = "35070")]
impl<'a, T: ?Sized> Display for BorrowError<'a, T> {
#[stable(feature = "try_borrow", since = "1.13.0")]
impl Display for BorrowError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt("already mutably borrowed", f)
}
}
/// An error returned by [`RefCell::try_borrow_mut`](struct.RefCell.html#method.try_borrow_mut).
#[unstable(feature = "try_borrow", issue = "35070")]
pub struct BorrowMutError<'a, T: 'a + ?Sized> {
marker: PhantomData<&'a RefCell<T>>,
#[stable(feature = "try_borrow", since = "1.13.0")]
pub struct BorrowMutError {
_private: (),
}
#[unstable(feature = "try_borrow", issue = "35070")]
impl<'a, T: ?Sized> Debug for BorrowMutError<'a, T> {
#[stable(feature = "try_borrow", since = "1.13.0")]
impl Debug for BorrowMutError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("BorrowMutError").finish()
}
}
#[unstable(feature = "try_borrow", issue = "35070")]
impl<'a, T: ?Sized> Display for BorrowMutError<'a, T> {
#[stable(feature = "try_borrow", since = "1.13.0")]
impl Display for BorrowMutError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt("already borrowed", f)
}
@ -573,8 +573,6 @@ impl<T: ?Sized> RefCell<T> {
/// # Examples
///
/// ```
/// #![feature(try_borrow)]
///
/// use std::cell::RefCell;
///
/// let c = RefCell::new(5);
@ -589,15 +587,15 @@ impl<T: ?Sized> RefCell<T> {
/// assert!(c.try_borrow().is_ok());
/// }
/// ```
#[unstable(feature = "try_borrow", issue = "35070")]
#[stable(feature = "try_borrow", since = "1.13.0")]
#[inline]
pub fn try_borrow(&self) -> Result<Ref<T>, BorrowError<T>> {
pub fn try_borrow(&self) -> Result<Ref<T>, BorrowError> {
match BorrowRef::new(&self.borrow) {
Some(b) => Ok(Ref {
value: unsafe { &*self.value.get() },
borrow: b,
}),
None => Err(BorrowError { marker: PhantomData }),
None => Err(BorrowError { _private: () }),
}
}
@ -654,8 +652,6 @@ impl<T: ?Sized> RefCell<T> {
/// # Examples
///
/// ```
/// #![feature(try_borrow)]
///
/// use std::cell::RefCell;
///
/// let c = RefCell::new(5);
@ -667,15 +663,15 @@ impl<T: ?Sized> RefCell<T> {
///
/// assert!(c.try_borrow_mut().is_ok());
/// ```
#[unstable(feature = "try_borrow", issue = "35070")]
#[stable(feature = "try_borrow", since = "1.13.0")]
#[inline]
pub fn try_borrow_mut(&self) -> Result<RefMut<T>, BorrowMutError<T>> {
pub fn try_borrow_mut(&self) -> Result<RefMut<T>, BorrowMutError> {
match BorrowRefMut::new(&self.borrow) {
Some(b) => Ok(RefMut {
value: unsafe { &mut *self.value.get() },
borrow: b,
}),
None => Err(BorrowMutError { marker: PhantomData }),
None => Err(BorrowMutError { _private: () }),
}
}

View file

@ -18,6 +18,7 @@
use char_private::is_printable;
use convert::TryFrom;
use fmt;
use slice;
use iter::FusedIterator;
use mem::transmute;
@ -327,9 +328,9 @@ pub trait CharExt {
#[stable(feature = "core", since = "1.6.0")]
fn len_utf16(self) -> usize;
#[unstable(feature = "unicode", issue = "27784")]
fn encode_utf8(self) -> EncodeUtf8;
fn encode_utf8(self, dst: &mut [u8]) -> &mut str;
#[unstable(feature = "unicode", issue = "27784")]
fn encode_utf16(self) -> EncodeUtf16;
fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16];
}
#[stable(feature = "core", since = "1.6.0")]
@ -419,47 +420,59 @@ impl CharExt for char {
}
#[inline]
fn encode_utf8(self) -> EncodeUtf8 {
fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
let code = self as u32;
let mut buf = [0; 4];
let pos = if code < MAX_ONE_B {
buf[3] = code as u8;
3
} else if code < MAX_TWO_B {
buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
2
} else if code < MAX_THREE_B {
buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
1
} else {
buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
0
};
EncodeUtf8 { buf: buf, pos: pos }
unsafe {
let len =
if code < MAX_ONE_B && !dst.is_empty() {
*dst.get_unchecked_mut(0) = code as u8;
1
} else if code < MAX_TWO_B && dst.len() >= 2 {
*dst.get_unchecked_mut(0) = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
*dst.get_unchecked_mut(1) = (code & 0x3F) as u8 | TAG_CONT;
2
} else if code < MAX_THREE_B && dst.len() >= 3 {
*dst.get_unchecked_mut(0) = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
*dst.get_unchecked_mut(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
*dst.get_unchecked_mut(2) = (code & 0x3F) as u8 | TAG_CONT;
3
} else if dst.len() >= 4 {
*dst.get_unchecked_mut(0) = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
*dst.get_unchecked_mut(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT;
*dst.get_unchecked_mut(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
*dst.get_unchecked_mut(3) = (code & 0x3F) as u8 | TAG_CONT;
4
} else {
panic!("encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
from_u32_unchecked(code).len_utf8(),
code,
dst.len())
};
transmute(slice::from_raw_parts_mut(dst.as_mut_ptr(), len))
}
}
#[inline]
fn encode_utf16(self) -> EncodeUtf16 {
let mut buf = [0; 2];
fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] {
let mut code = self as u32;
let pos = if (code & 0xFFFF) == code {
// The BMP falls through (assuming non-surrogate, as it should)
buf[1] = code as u16;
1
} else {
// Supplementary planes break into surrogates.
code -= 0x1_0000;
buf[0] = 0xD800 | ((code >> 10) as u16);
buf[1] = 0xDC00 | ((code as u16) & 0x3FF);
0
};
EncodeUtf16 { buf: buf, pos: pos }
unsafe {
if (code & 0xFFFF) == code && !dst.is_empty() {
// The BMP falls through (assuming non-surrogate, as it should)
*dst.get_unchecked_mut(0) = code as u16;
slice::from_raw_parts_mut(dst.as_mut_ptr(), 1)
} else if dst.len() >= 2 {
// Supplementary planes break into surrogates.
code -= 0x1_0000;
*dst.get_unchecked_mut(0) = 0xD800 | ((code >> 10) as u16);
*dst.get_unchecked_mut(1) = 0xDC00 | ((code as u16) & 0x3FF);
slice::from_raw_parts_mut(dst.as_mut_ptr(), 2)
} else {
panic!("encode_utf16: need {} units to encode U+{:X}, but the buffer has {}",
from_u32_unchecked(code).len_utf16(),
code,
dst.len())
}
}
}
}
@ -702,88 +715,7 @@ impl ExactSizeIterator for EscapeDebug { }
#[unstable(feature = "fused", issue = "35602")]
impl FusedIterator for EscapeDebug {}
/// An iterator over `u8` entries represending the UTF-8 encoding of a `char`
/// value.
///
/// Constructed via the `.encode_utf8()` method on `char`.
#[unstable(feature = "unicode", issue = "27784")]
#[derive(Debug)]
pub struct EncodeUtf8 {
buf: [u8; 4],
pos: usize,
}
impl EncodeUtf8 {
/// Returns the remaining bytes of this iterator as a slice.
#[unstable(feature = "unicode", issue = "27784")]
pub fn as_slice(&self) -> &[u8] {
&self.buf[self.pos..]
}
}
#[unstable(feature = "unicode", issue = "27784")]
impl Iterator for EncodeUtf8 {
type Item = u8;
fn next(&mut self) -> Option<u8> {
if self.pos == self.buf.len() {
None
} else {
let ret = Some(self.buf[self.pos]);
self.pos += 1;
ret
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.as_slice().iter().size_hint()
}
}
#[unstable(feature = "fused", issue = "35602")]
impl FusedIterator for EncodeUtf8 {}
/// An iterator over `u16` entries represending the UTF-16 encoding of a `char`
/// value.
///
/// Constructed via the `.encode_utf16()` method on `char`.
#[unstable(feature = "unicode", issue = "27784")]
#[derive(Debug)]
pub struct EncodeUtf16 {
buf: [u16; 2],
pos: usize,
}
impl EncodeUtf16 {
/// Returns the remaining bytes of this iterator as a slice.
#[unstable(feature = "unicode", issue = "27784")]
pub fn as_slice(&self) -> &[u16] {
&self.buf[self.pos..]
}
}
#[unstable(feature = "unicode", issue = "27784")]
impl Iterator for EncodeUtf16 {
type Item = u16;
fn next(&mut self) -> Option<u16> {
if self.pos == self.buf.len() {
None
} else {
let ret = Some(self.buf[self.pos]);
self.pos += 1;
ret
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.as_slice().iter().size_hint()
}
}
#[unstable(feature = "fused", issue = "35602")]
impl FusedIterator for EncodeUtf16 {}
/// An iterator over an iterator of bytes of the characters the bytes represent
/// as UTF-8
@ -800,7 +732,7 @@ pub fn decode_utf8<I: IntoIterator<Item = u8>>(i: I) -> DecodeUtf8<I::IntoIter>
/// `<DecodeUtf8 as Iterator>::next` returns this for an invalid input sequence.
#[unstable(feature = "decode_utf8", issue = "33906")]
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Eq, Debug)]
pub struct InvalidSequence(());
#[unstable(feature = "decode_utf8", issue = "33906")]

View file

@ -129,13 +129,6 @@ pub struct AssertParamIsClone<T: Clone + ?Sized> { _field: ::marker::PhantomData
reason = "deriving hack, should not be public",
issue = "0")]
pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: ::marker::PhantomData<T> }
#[cfg(stage0)]
#[doc(hidden)]
#[inline(always)]
#[unstable(feature = "derive_clone_copy",
reason = "deriving hack, should not be public",
issue = "0")]
pub fn assert_receiver_is_clone<T: Clone + ?Sized>(_: &T) {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Clone for &'a T {

View file

@ -10,10 +10,13 @@
//! Functionality for ordering and comparison.
//!
//! This module defines both `PartialOrd` and `PartialEq` traits which are used
//! This module defines both [`PartialOrd`] and [`PartialEq`] traits which are used
//! by the compiler to implement comparison operators. Rust programs may
//! implement `PartialOrd` to overload the `<`, `<=`, `>`, and `>=` operators,
//! and may implement `PartialEq` to overload the `==` and `!=` operators.
//! implement [`PartialOrd`] to overload the `<`, `<=`, `>`, and `>=` operators,
//! and may implement [`PartialEq`] to overload the `==` and `!=` operators.
//!
//! [`PartialOrd`]: trait.PartialOrd.html
//! [`PartialEq`]: trait.PartialEq.html
//!
//! # Examples
//!
@ -777,24 +780,24 @@ mod impls {
ord_impl! { char usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[unstable(feature = "never_type", issue = "35121")]
#[unstable(feature = "never_type_impls", issue = "35121")]
impl PartialEq for ! {
fn eq(&self, _: &!) -> bool {
*self
}
}
#[unstable(feature = "never_type", issue = "35121")]
#[unstable(feature = "never_type_impls", issue = "35121")]
impl Eq for ! {}
#[unstable(feature = "never_type", issue = "35121")]
#[unstable(feature = "never_type_impls", issue = "35121")]
impl PartialOrd for ! {
fn partial_cmp(&self, _: &!) -> Option<Ordering> {
*self
}
}
#[unstable(feature = "never_type", issue = "35121")]
#[unstable(feature = "never_type_impls", issue = "35121")]
impl Ord for ! {
fn cmp(&self, _: &!) -> Ordering {
*self

View file

@ -92,6 +92,22 @@ pub trait AsRef<T: ?Sized> {
/// [`Option<T>`]: ../../std/option/enum.Option.html
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
///
/// # Examples
///
/// [`Box<T>`] implements `AsMut<T>`:
///
/// [`Box<T>`]: ../../std/boxed/struct.Box.html
///
/// ```
/// fn add_one<T: AsMut<u64>>(num: &mut T) {
/// *num.as_mut() += 1;
/// }
///
/// let mut boxed_num = Box::new(0);
/// add_one(&mut boxed_num);
/// assert_eq!(*boxed_num, 1);
/// ```
///
/// # Generic Impls
///
/// - `AsMut` auto-dereferences if the inner type is a reference or a mutable

View file

@ -97,9 +97,7 @@ pub trait Write {
/// This function will return an instance of `Error` on error.
#[stable(feature = "fmt_write_char", since = "1.1.0")]
fn write_char(&mut self, c: char) -> Result {
self.write_str(unsafe {
str::from_utf8_unchecked(c.encode_utf8().as_slice())
})
self.write_str(c.encode_utf8(&mut [0; 4]))
}
/// Glue for usage of the `write!` macro with implementors of this trait.
@ -272,10 +270,14 @@ impl<'a> Arguments<'a> {
/// safely be done so, so no constructors are given and the fields are private
/// to prevent modification.
///
/// The `format_args!` macro will safely create an instance of this structure
/// The [`format_args!`] macro will safely create an instance of this structure
/// and pass it to a function or closure, passed as the first argument. The
/// macro validates the format string at compile-time so usage of the `write`
/// and `format` functions can be safely performed.
/// macro validates the format string at compile-time so usage of the [`write`]
/// and [`format`] functions can be safely performed.
///
/// [`format_args!`]: ../../std/macro.format_args.html
/// [`format`]: ../../std/fmt/fn.format.html
/// [`write`]: ../../std/fmt/fn.write.html
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Copy, Clone)]
pub struct Arguments<'a> {
@ -792,7 +794,7 @@ pub trait UpperExp {
/// assert_eq!(output, "Hello world!");
/// ```
///
/// Please note that using [`write!`][write_macro] might be preferrable. Example:
/// Please note that using [`write!`] might be preferrable. Example:
///
/// ```
/// use std::fmt::Write;
@ -803,7 +805,7 @@ pub trait UpperExp {
/// assert_eq!(output, "Hello world!");
/// ```
///
/// [write_macro]: ../../std/macro.write!.html
/// [`write!`]: ../../std/macro.write.html
#[stable(feature = "rust1", since = "1.0.0")]
pub fn write(output: &mut Write, args: Arguments) -> Result {
let mut formatter = Formatter {
@ -920,9 +922,7 @@ impl<'a> Formatter<'a> {
// Writes the sign if it exists, and then the prefix if it was requested
let write_prefix = |f: &mut Formatter| {
if let Some(c) = sign {
f.buf.write_str(unsafe {
str::from_utf8_unchecked(c.encode_utf8().as_slice())
})?;
f.buf.write_str(c.encode_utf8(&mut [0; 4]))?;
}
if prefixed { f.buf.write_str(prefix) }
else { Ok(()) }
@ -1028,10 +1028,8 @@ impl<'a> Formatter<'a> {
rt::v1::Alignment::Center => (padding / 2, (padding + 1) / 2),
};
let fill = self.fill.encode_utf8();
let fill = unsafe {
str::from_utf8_unchecked(fill.as_slice())
};
let mut fill = [0; 4];
let fill = self.fill.encode_utf8(&mut fill);
for _ in 0..pre_pad {
self.buf.write_str(fill)?;
@ -1358,14 +1356,14 @@ macro_rules! fmt_refs {
fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp }
#[unstable(feature = "never_type", issue = "35121")]
#[unstable(feature = "never_type_impls", issue = "35121")]
impl Debug for ! {
fn fmt(&self, _: &mut Formatter) -> Result {
*self
}
}
#[unstable(feature = "never_type", issue = "35121")]
#[unstable(feature = "never_type_impls", issue = "35121")]
impl Display for ! {
fn fmt(&self, _: &mut Formatter) -> Result {
*self
@ -1431,9 +1429,7 @@ impl Display for char {
if f.width.is_none() && f.precision.is_none() {
f.write_char(*self)
} else {
f.pad(unsafe {
str::from_utf8_unchecked(self.encode_utf8().as_slice())
})
f.pad(self.encode_utf8(&mut [0; 4]))
}
}
}
@ -1570,11 +1566,11 @@ floating! { f64 }
// Implementation of Display/Debug for various core types
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Debug for *const T {
impl<T: ?Sized> Debug for *const T {
fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Debug for *mut T {
impl<T: ?Sized> Debug for *mut T {
fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) }
}

View file

@ -31,7 +31,7 @@ pub struct FormatSpec {
}
/// Possible alignments that can be requested as part of a formatting directive.
#[derive(Copy, Clone, PartialEq)]
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Alignment {
/// Indication that contents should be left-aligned.
Left,

View file

@ -38,7 +38,9 @@
//! ```
//!
//! If you need more control over how a value is hashed, you need to implement
//! the `Hash` trait:
//! the [`Hash`] trait:
//!
//! [`Hash`]: trait.Hash.html
//!
//! ```rust
//! use std::hash::{Hash, Hasher, SipHasher};
@ -76,9 +78,11 @@ use marker;
use mem;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub use self::sip::SipHasher;
#[unstable(feature = "sip_hash_13", issue = "29754")]
#[allow(deprecated)]
pub use self::sip::{SipHasher13, SipHasher24};
mod sip;
@ -88,7 +92,7 @@ mod sip;
/// The `H` type parameter is an abstract hash state that is used by the `Hash`
/// to compute the hash.
///
/// If you are also implementing `Eq`, there is an additional property that
/// If you are also implementing [`Eq`], there is an additional property that
/// is important:
///
/// ```text
@ -96,13 +100,13 @@ mod sip;
/// ```
///
/// In other words, if two keys are equal, their hashes should also be equal.
/// `HashMap` and `HashSet` both rely on this behavior.
/// [`HashMap`] and [`HashSet`] both rely on this behavior.
///
/// ## Derivable
///
/// This trait can be used with `#[derive]` if all fields implement `Hash`.
/// When `derive`d, the resulting hash will be the combination of the values
/// from calling `.hash()` on each field.
/// from calling [`.hash()`] on each field.
///
/// ## How can I implement `Hash`?
///
@ -125,6 +129,11 @@ mod sip;
/// }
/// }
/// ```
///
/// [`Eq`]: ../../std/cmp/trait.Eq.html
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
/// [`HashSet`]: ../../std/collections/struct.HashSet.html
/// [`.hash()`]: #tymethod.hash
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hash {
/// Feeds this value into the state given, updating the hasher as necessary.
@ -149,35 +158,35 @@ pub trait Hasher {
#[stable(feature = "rust1", since = "1.0.0")]
fn finish(&self) -> u64;
/// Writes some data into this `Hasher`
/// Writes some data into this `Hasher`.
#[stable(feature = "rust1", since = "1.0.0")]
fn write(&mut self, bytes: &[u8]);
/// Write a single `u8` into this hasher
/// Write a single `u8` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_u8(&mut self, i: u8) {
self.write(&[i])
}
/// Write a single `u16` into this hasher.
/// Writes a single `u16` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_u16(&mut self, i: u16) {
self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
}
/// Write a single `u32` into this hasher.
/// Writes a single `u32` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_u32(&mut self, i: u32) {
self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
}
/// Write a single `u64` into this hasher.
/// Writes a single `u64` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_u64(&mut self, i: u64) {
self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
}
/// Write a single `usize` into this hasher.
/// Writes a single `usize` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_usize(&mut self, i: usize) {
@ -187,31 +196,31 @@ pub trait Hasher {
self.write(bytes);
}
/// Write a single `i8` into this hasher.
/// Writes a single `i8` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_i8(&mut self, i: i8) {
self.write_u8(i as u8)
}
/// Write a single `i16` into this hasher.
/// Writes a single `i16` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_i16(&mut self, i: i16) {
self.write_u16(i as u16)
}
/// Write a single `i32` into this hasher.
/// Writes a single `i32` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_i32(&mut self, i: i32) {
self.write_u32(i as u32)
}
/// Write a single `i64` into this hasher.
/// Writes a single `i64` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_i64(&mut self, i: i64) {
self.write_u64(i as u64)
}
/// Write a single `isize` into this hasher.
/// Writes a single `isize` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_isize(&mut self, i: isize) {

View file

@ -10,13 +10,21 @@
//! An implementation of SipHash.
#![allow(deprecated)]
use marker::PhantomData;
use ptr;
use cmp;
use mem;
/// An implementation of SipHash 1-3.
///
/// This is currently the default hashing function used by standard library
/// (eg. `collections::HashMap` uses it by default).
///
/// See: https://131002.net/siphash/
#[unstable(feature = "sip_hash_13", issue = "34767")]
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
#[derive(Debug, Clone, Default)]
pub struct SipHasher13 {
hasher: Hasher<Sip13Rounds>,
@ -26,6 +34,7 @@ pub struct SipHasher13 {
///
/// See: https://131002.net/siphash/
#[unstable(feature = "sip_hash_13", issue = "34767")]
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
#[derive(Debug, Clone, Default)]
pub struct SipHasher24 {
hasher: Hasher<Sip24Rounds>,
@ -35,9 +44,6 @@ pub struct SipHasher24 {
///
/// See: https://131002.net/siphash/
///
/// This is currently the default hashing function used by standard library
/// (eg. `collections::HashMap` uses it by default).
///
/// SipHash is a general-purpose hashing function: it runs at a good
/// speed (competitive with Spooky and City) and permits strong _keyed_
/// hashing. This lets you key your hashtables from a strong RNG, such as
@ -47,6 +53,7 @@ pub struct SipHasher24 {
/// it is not intended for cryptographic purposes. As such, all
/// cryptographic uses of this implementation are _strongly discouraged_.
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
#[derive(Debug, Clone, Default)]
pub struct SipHasher(SipHasher24);
@ -73,69 +80,67 @@ struct State {
v3: u64,
}
// sadly, these macro definitions can't appear later,
// because they're needed in the following defs;
// this design could be improved.
macro_rules! u8to64_le {
($buf:expr, $i:expr) =>
($buf[0+$i] as u64 |
($buf[1+$i] as u64) << 8 |
($buf[2+$i] as u64) << 16 |
($buf[3+$i] as u64) << 24 |
($buf[4+$i] as u64) << 32 |
($buf[5+$i] as u64) << 40 |
($buf[6+$i] as u64) << 48 |
($buf[7+$i] as u64) << 56);
($buf:expr, $i:expr, $len:expr) =>
({
let mut t = 0;
let mut out = 0;
while t < $len {
out |= ($buf[t+$i] as u64) << t*8;
t += 1;
}
out
});
}
/// Load a full u64 word from a byte stream, in LE order. Use
/// `copy_nonoverlapping` to let the compiler generate the most efficient way
/// to load u64 from a possibly unaligned address.
///
/// Unsafe because: unchecked indexing at i..i+8
#[inline]
unsafe fn load_u64_le(buf: &[u8], i: usize) -> u64 {
debug_assert!(i + 8 <= buf.len());
let mut data = 0u64;
ptr::copy_nonoverlapping(buf.get_unchecked(i), &mut data as *mut _ as *mut u8, 8);
data.to_le()
}
macro_rules! rotl {
($x:expr, $b:expr) =>
(($x << $b) | ($x >> (64_i32.wrapping_sub($b))))
}
macro_rules! compress {
($state:expr) => ({
compress!($state.v0, $state.v1, $state.v2, $state.v3)
});
($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
({
$v0 = $v0.wrapping_add($v1); $v1 = rotl!($v1, 13); $v1 ^= $v0;
$v0 = rotl!($v0, 32);
$v2 = $v2.wrapping_add($v3); $v3 = rotl!($v3, 16); $v3 ^= $v2;
$v0 = $v0.wrapping_add($v3); $v3 = rotl!($v3, 21); $v3 ^= $v0;
$v2 = $v2.wrapping_add($v1); $v1 = rotl!($v1, 17); $v1 ^= $v2;
$v2 = rotl!($v2, 32);
$v0 = $v0.wrapping_add($v1); $v1 = $v1.rotate_left(13); $v1 ^= $v0;
$v0 = $v0.rotate_left(32);
$v2 = $v2.wrapping_add($v3); $v3 = $v3.rotate_left(16); $v3 ^= $v2;
$v0 = $v0.wrapping_add($v3); $v3 = $v3.rotate_left(21); $v3 ^= $v0;
$v2 = $v2.wrapping_add($v1); $v1 = $v1.rotate_left(17); $v1 ^= $v2;
$v2 = $v2.rotate_left(32);
});
}
/// Load an integer of the desired type from a byte stream, in LE order. Uses
/// `copy_nonoverlapping` to let the compiler generate the most efficient way
/// to load it from a possibly unaligned address.
///
/// Unsafe because: unchecked indexing at i..i+size_of(int_ty)
macro_rules! load_int_le {
($buf:expr, $i:expr, $int_ty:ident) =>
({
debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len());
let mut data = 0 as $int_ty;
ptr::copy_nonoverlapping($buf.get_unchecked($i),
&mut data as *mut _ as *mut u8,
mem::size_of::<$int_ty>());
data.to_le()
});
}
/// Load an u64 using up to 7 bytes of a byte slice.
///
/// Unsafe because: unchecked indexing at start..start+len
#[inline]
unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
debug_assert!(len < 8);
let mut i = 0; // current byte index (from LSB) in the output u64
let mut out = 0;
if i + 3 < len {
out = load_int_le!(buf, start + i, u32) as u64;
i += 4;
}
if i + 1 < len {
out |= (load_int_le!(buf, start + i, u16) as u64) << (i * 8);
i += 2
}
if i < len {
out |= (*buf.get_unchecked(start + i) as u64) << (i * 8);
i += 1;
}
debug_assert_eq!(i, len);
out
}
impl SipHasher {
/// Creates a new `SipHasher` with the two initial keys set to 0.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
pub fn new() -> SipHasher {
SipHasher::new_with_keys(0, 0)
}
@ -143,16 +148,17 @@ impl SipHasher {
/// Creates a `SipHasher` that is keyed off the provided keys.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
SipHasher(SipHasher24::new_with_keys(key0, key1))
}
}
impl SipHasher13 {
/// Creates a new `SipHasher13` with the two initial keys set to 0.
#[inline]
#[unstable(feature = "sip_hash_13", issue = "34767")]
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
pub fn new() -> SipHasher13 {
SipHasher13::new_with_keys(0, 0)
}
@ -160,6 +166,7 @@ impl SipHasher13 {
/// Creates a `SipHasher13` that is keyed off the provided keys.
#[inline]
#[unstable(feature = "sip_hash_13", issue = "34767")]
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 {
SipHasher13 {
hasher: Hasher::new_with_keys(key0, key1)
@ -171,6 +178,7 @@ impl SipHasher24 {
/// Creates a new `SipHasher24` with the two initial keys set to 0.
#[inline]
#[unstable(feature = "sip_hash_13", issue = "34767")]
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
pub fn new() -> SipHasher24 {
SipHasher24::new_with_keys(0, 0)
}
@ -178,6 +186,7 @@ impl SipHasher24 {
/// Creates a `SipHasher24` that is keyed off the provided keys.
#[inline]
#[unstable(feature = "sip_hash_13", issue = "34767")]
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher24 {
SipHasher24 {
hasher: Hasher::new_with_keys(key0, key1)
@ -215,6 +224,37 @@ impl<S: Sip> Hasher<S> {
self.state.v3 = self.k1 ^ 0x7465646279746573;
self.ntail = 0;
}
// Specialized write function that is only valid for buffers with len <= 8.
// It's used to force inlining of write_u8 and write_usize, those would normally be inlined
// except for composite types (that includes slices and str hashing because of delimiter).
// Without this extra push the compiler is very reluctant to inline delimiter writes,
// degrading performance substantially for the most common use cases.
#[inline(always)]
fn short_write(&mut self, msg: &[u8]) {
debug_assert!(msg.len() <= 8);
let length = msg.len();
self.length += length;
let needed = 8 - self.ntail;
let fill = cmp::min(length, needed);
if fill == 8 {
self.tail = unsafe { load_int_le!(msg, 0, u64) };
} else {
self.tail |= unsafe { u8to64_le(msg, 0, fill) } << (8 * self.ntail);
if length < needed {
self.ntail += length;
return;
}
}
self.state.v3 ^= self.tail;
S::c_rounds(&mut self.state);
self.state.v0 ^= self.tail;
// Buffered tail is now flushed, process new input.
self.ntail = length - needed;
self.tail = unsafe { u8to64_le(msg, needed, self.ntail) };
}
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -257,6 +297,21 @@ impl super::Hasher for SipHasher24 {
}
impl<S: Sip> super::Hasher for Hasher<S> {
// see short_write comment for explanation
#[inline]
fn write_usize(&mut self, i: usize) {
let bytes = unsafe {
::slice::from_raw_parts(&i as *const usize as *const u8, mem::size_of::<usize>())
};
self.short_write(bytes);
}
// see short_write comment for explanation
#[inline]
fn write_u8(&mut self, i: u8) {
self.short_write(&[i]);
}
#[inline]
fn write(&mut self, msg: &[u8]) {
let length = msg.len();
@ -266,19 +321,16 @@ impl<S: Sip> super::Hasher for Hasher<S> {
if self.ntail != 0 {
needed = 8 - self.ntail;
self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << 8 * self.ntail;
if length < needed {
self.tail |= u8to64_le!(msg, 0, length) << 8 * self.ntail;
self.ntail += length;
return
} else {
self.state.v3 ^= self.tail;
S::c_rounds(&mut self.state);
self.state.v0 ^= self.tail;
self.ntail = 0;
}
let m = self.tail | u8to64_le!(msg, 0, needed) << 8 * self.ntail;
self.state.v3 ^= m;
S::c_rounds(&mut self.state);
self.state.v0 ^= m;
self.ntail = 0;
}
// Buffered tail is now flushed, process new input.
@ -287,7 +339,7 @@ impl<S: Sip> super::Hasher for Hasher<S> {
let mut i = needed;
while i < len - left {
let mi = unsafe { load_u64_le(msg, i) };
let mi = unsafe { load_int_le!(msg, i, u64) };
self.state.v3 ^= mi;
S::c_rounds(&mut self.state);
@ -296,7 +348,7 @@ impl<S: Sip> super::Hasher for Hasher<S> {
i += 8;
}
self.tail = u8to64_le!(msg, i, left);
self.tail = unsafe { u8to64_le(msg, i, left) };
self.ntail = left;
}

View file

@ -194,14 +194,12 @@ extern "rust-intrinsic" {
/// own, or if it does not enable any significant optimizations.
pub fn assume(b: bool);
#[cfg(not(stage0))]
/// Hints to the compiler that branch condition is likely to be true.
/// Returns the value passed to it.
///
/// Any use other than with `if` statements will probably not have an effect.
pub fn likely(b: bool) -> bool;
#[cfg(not(stage0))]
/// Hints to the compiler that branch condition is likely to be false.
/// Returns the value passed to it.
///
@ -596,6 +594,19 @@ extern "rust-intrinsic" {
/// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
/// bytes of memory starting at `dst` to `val`.
///
/// # Examples
///
/// ```
/// use std::ptr;
///
/// let mut vec = vec![0; 4];
/// unsafe {
/// let vec_ptr = vec.as_mut_ptr();
/// ptr::write_bytes(vec_ptr, b'a', 2);
/// }
/// assert_eq!(vec, [b'a', b'a', 0, 0]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);

View file

@ -195,13 +195,9 @@ pub trait Iterator {
last
}
/// Consumes the `n` first elements of the iterator, then returns the
/// `next()` one.
/// Returns the `n`th element of the iterator.
///
/// This method will evaluate the iterator `n` times, discarding those elements.
/// After it does so, it will call [`next()`] and return its value.
///
/// [`next()`]: #tymethod.next
/// Note that all preceding elements will be consumed (i.e. discarded).
///
/// Like most indexing operations, the count starts from zero, so `nth(0)`
/// returns the first value, `nth(1)` the second, and so on.

View file

@ -386,7 +386,7 @@ pub struct Cloned<I> {
it: I,
}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "iter_cloned", since = "1.1.0")]
impl<'a, I, T: 'a> Iterator for Cloned<I>
where I: Iterator<Item=&'a T>, T: Clone
{
@ -399,9 +399,15 @@ impl<'a, I, T: 'a> Iterator for Cloned<I>
fn size_hint(&self) -> (usize, Option<usize>) {
self.it.size_hint()
}
fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
where F: FnMut(Acc, Self::Item) -> Acc,
{
self.it.fold(init, move |acc, elt| f(acc, elt.clone()))
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "iter_cloned", since = "1.1.0")]
impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I>
where I: DoubleEndedIterator<Item=&'a T>, T: Clone
{
@ -410,7 +416,7 @@ impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I>
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "iter_cloned", since = "1.1.0")]
impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
where I: ExactSizeIterator<Item=&'a T>, T: Clone
{}
@ -420,6 +426,18 @@ impl<'a, I, T: 'a> FusedIterator for Cloned<I>
where I: FusedIterator<Item=&'a T>, T: Clone
{}
#[doc(hidden)]
unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I>
where I: TrustedRandomAccess<Item=&'a T>, T: Clone
{
unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item {
self.it.get_unchecked(i).clone()
}
#[inline]
fn may_have_side_effect() -> bool { true }
}
/// An iterator that repeats endlessly.
///
/// This `struct` is created by the [`cycle()`] method on [`Iterator`]. See its
@ -532,6 +550,25 @@ impl<A, B> Iterator for Chain<A, B> where
}
}
fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
where F: FnMut(Acc, Self::Item) -> Acc,
{
let mut accum = init;
match self.state {
ChainState::Both | ChainState::Front => {
accum = self.a.fold(accum, &mut f);
}
_ => { }
}
match self.state {
ChainState::Both | ChainState::Back => {
accum = self.b.fold(accum, &mut f);
}
_ => { }
}
accum
}
#[inline]
fn nth(&mut self, mut n: usize) -> Option<A::Item> {
match self.state {
@ -643,7 +680,9 @@ impl<A, B> FusedIterator for Chain<A, B>
pub struct Zip<A, B> {
a: A,
b: B,
spec: <(A, B) as ZipImplData>::Data,
// index and len are only used by the specialized version of zip
index: usize,
len: usize,
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -685,17 +724,6 @@ trait ZipImpl<A, B> {
B: DoubleEndedIterator + ExactSizeIterator;
}
// Zip specialization data members
#[doc(hidden)]
trait ZipImplData {
type Data: 'static + Clone + Default + fmt::Debug;
}
#[doc(hidden)]
impl<T> ZipImplData for T {
default type Data = ();
}
// General Zip impl
#[doc(hidden)]
impl<A, B> ZipImpl<A, B> for Zip<A, B>
@ -706,7 +734,8 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
Zip {
a: a,
b: b,
spec: Default::default(), // unused
index: 0, // unused
len: 0, // unused
}
}
@ -759,20 +788,6 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
}
}
#[doc(hidden)]
#[derive(Default, Debug, Clone)]
struct ZipImplFields {
index: usize,
len: usize,
}
#[doc(hidden)]
impl<A, B> ZipImplData for (A, B)
where A: TrustedRandomAccess, B: TrustedRandomAccess
{
type Data = ZipImplFields;
}
#[doc(hidden)]
impl<A, B> ZipImpl<A, B> for Zip<A, B>
where A: TrustedRandomAccess, B: TrustedRandomAccess
@ -782,21 +797,26 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
Zip {
a: a,
b: b,
spec: ZipImplFields {
index: 0,
len: len,
}
index: 0,
len: len,
}
}
#[inline]
fn next(&mut self) -> Option<(A::Item, B::Item)> {
if self.spec.index < self.spec.len {
let i = self.spec.index;
self.spec.index += 1;
if self.index < self.len {
let i = self.index;
self.index += 1;
unsafe {
Some((self.a.get_unchecked(i), self.b.get_unchecked(i)))
}
} else if A::may_have_side_effect() && self.index < self.a.len() {
// match the base implementation's potential side effects
unsafe {
self.a.get_unchecked(self.index);
}
self.index += 1;
None
} else {
None
}
@ -804,7 +824,7 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.spec.len - self.spec.index;
let len = self.len - self.index;
(len, Some(len))
}
@ -813,9 +833,26 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
where A: DoubleEndedIterator + ExactSizeIterator,
B: DoubleEndedIterator + ExactSizeIterator
{
if self.spec.index < self.spec.len {
self.spec.len -= 1;
let i = self.spec.len;
// Adjust a, b to equal length
if A::may_have_side_effect() {
let sz = self.a.len();
if sz > self.len {
for _ in 0..sz - cmp::max(self.len, self.index) {
self.a.next_back();
}
}
}
if B::may_have_side_effect() {
let sz = self.b.len();
if sz > self.len {
for _ in 0..sz - self.len {
self.b.next_back();
}
}
}
if self.index < self.len {
self.len -= 1;
let i = self.len;
unsafe {
Some((self.a.get_unchecked(i), self.b.get_unchecked(i)))
}
@ -838,6 +875,9 @@ unsafe impl<A, B> TrustedRandomAccess for Zip<A, B>
(self.a.get_unchecked(i), self.b.get_unchecked(i))
}
fn may_have_side_effect() -> bool {
A::may_have_side_effect() || B::may_have_side_effect()
}
}
#[unstable(feature = "fused", issue = "35602")]
@ -924,6 +964,13 @@ impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B {
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
fn fold<Acc, G>(self, init: Acc, mut g: G) -> Acc
where G: FnMut(Acc, Self::Item) -> Acc,
{
let mut f = self.f;
self.iter.fold(init, move |acc, elt| g(acc, f(elt)))
}
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -944,6 +991,18 @@ impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F>
impl<B, I: FusedIterator, F> FusedIterator for Map<I, F>
where F: FnMut(I::Item) -> B {}
#[doc(hidden)]
unsafe impl<B, I, F> TrustedRandomAccess for Map<I, F>
where I: TrustedRandomAccess,
F: FnMut(I::Item) -> B,
{
unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item {
(self.f)(self.iter.get_unchecked(i))
}
#[inline]
fn may_have_side_effect() -> bool { true }
}
/// An iterator that filters the elements of `iter` with `predicate`.
///
/// This `struct` is created by the [`filter()`] method on [`Iterator`]. See its
@ -1159,6 +1218,10 @@ unsafe impl<I> TrustedRandomAccess for Enumerate<I>
unsafe fn get_unchecked(&mut self, i: usize) -> (usize, I::Item) {
(self.count + i, self.iter.get_unchecked(i))
}
fn may_have_side_effect() -> bool {
I::may_have_side_effect()
}
}
#[unstable(feature = "fused", issue = "35602")]
@ -1788,6 +1851,10 @@ unsafe impl<I> TrustedRandomAccess for Fuse<I>
unsafe fn get_unchecked(&mut self, i: usize) -> I::Item {
self.iter.get_unchecked(i)
}
fn may_have_side_effect() -> bool {
I::may_have_side_effect()
}
}
#[unstable(feature = "fused", issue = "35602")]

View file

@ -328,7 +328,8 @@ impl<A: Step> ops::RangeInclusive<A> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[unstable(feature = "step_by", reason = "recent addition",
issue = "27741")]
impl<A> Iterator for StepBy<A, ops::RangeFrom<A>> where
A: Clone,
for<'a> &'a A: Add<&'a A, Output = A>
@ -352,7 +353,8 @@ impl<A> Iterator for StepBy<A, ops::RangeFrom<A>> where
impl<A> FusedIterator for StepBy<A, ops::RangeFrom<A>>
where A: Clone, for<'a> &'a A: Add<&'a A, Output = A> {}
#[stable(feature = "rust1", since = "1.0.0")]
#[unstable(feature = "step_by", reason = "recent addition",
issue = "27741")]
impl<A: Step + Clone> Iterator for StepBy<A, ops::Range<A>> {
type Item = A;
@ -466,7 +468,11 @@ macro_rules! range_exact_iter_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
impl ExactSizeIterator for ops::Range<$t> { }
)*)
}
macro_rules! range_incl_exact_iter_impl {
($($t:ty)*) => ($(
#[unstable(feature = "inclusive_range",
reason = "recently added, follows RFC",
issue = "28237")]
@ -500,9 +506,12 @@ impl<A: Step> Iterator for ops::Range<A> where
}
}
// Ranges of u64 and i64 are excluded because they cannot guarantee having
// a length <= usize::MAX, which is required by ExactSizeIterator.
// These macros generate `ExactSizeIterator` impls for various range types.
// Range<{u,i}64> and RangeInclusive<{u,i}{32,64,size}> are excluded
// because they cannot guarantee having a length <= usize::MAX, which is
// required by ExactSizeIterator.
range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32);
range_incl_exact_iter_impl!(u8 u16 i8 i16);
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Step + Clone> DoubleEndedIterator for ops::Range<A> where

View file

@ -14,6 +14,7 @@
/// # Safety
///
/// The iterator's .len() and size_hint() must be exact.
/// `.len()` must be cheap to call.
///
/// .get_unchecked() must return distinct mutable references for distinct
/// indices (if applicable), and must return a valid reference if index is in
@ -21,5 +22,7 @@
#[doc(hidden)]
pub unsafe trait TrustedRandomAccess : ExactSizeIterator {
unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item;
/// Return `true` if getting an iterator element may have
/// side effects. Remember to take inner iterators into account.
fn may_have_side_effect() -> bool;
}

View file

@ -89,7 +89,7 @@
#![feature(specialization)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(question_mark)]
#![cfg_attr(stage0, feature(question_mark))]
#![feature(never_type)]
#![feature(prelude_import)]

View file

@ -119,6 +119,44 @@ macro_rules! assert_eq {
});
}
/// Asserts that two expressions are not equal to each other.
///
/// On panic, this macro will print the values of the expressions with their
/// debug representations.
///
/// # Examples
///
/// ```
/// let a = 3;
/// let b = 2;
/// assert_ne!(a, b);
/// ```
#[macro_export]
#[stable(feature = "assert_ne", since = "1.12.0")]
macro_rules! assert_ne {
($left:expr , $right:expr) => ({
match (&$left, &$right) {
(left_val, right_val) => {
if *left_val == *right_val {
panic!("assertion failed: `(left != right)` \
(left: `{:?}`, right: `{:?}`)", left_val, right_val)
}
}
}
});
($left:expr , $right:expr, $($arg:tt)*) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
if *left_val == *right_val {
panic!("assertion failed: `(left != right)` \
(left: `{:?}`, right: `{:?}`): {}", left_val, right_val,
format_args!($($arg)*))
}
}
}
});
}
/// Ensure that a boolean expression is `true` at runtime.
///
/// This will invoke the `panic!` macro if the provided expression cannot be
@ -189,9 +227,37 @@ macro_rules! debug_assert_eq {
($($arg:tt)*) => (if cfg!(debug_assertions) { assert_eq!($($arg)*); })
}
/// Asserts that two expressions are not equal to each other.
///
/// On panic, this macro will print the values of the expressions with their
/// debug representations.
///
/// Unlike `assert_ne!`, `debug_assert_ne!` statements are only enabled in non
/// optimized builds by default. An optimized build will omit all
/// `debug_assert_ne!` statements unless `-C debug-assertions` is passed to the
/// compiler. This makes `debug_assert_ne!` useful for checks that are too
/// expensive to be present in a release build but may be helpful during
/// development.
///
/// # Examples
///
/// ```
/// let a = 3;
/// let b = 2;
/// debug_assert_ne!(a, b);
/// ```
#[macro_export]
#[stable(feature = "assert_ne", since = "1.12.0")]
macro_rules! debug_assert_ne {
($($arg:tt)*) => (if cfg!(debug_assertions) { assert_ne!($($arg)*); })
}
/// Helper macro for reducing boilerplate code for matching `Result` together
/// with converting downstream errors.
///
/// Prefer using `?` syntax to `try!`. `?` is built in to the language and is
/// more succinct than `try!`. It is the standard method for error propagation.
///
/// `try!` matches the given `Result`. In case of the `Ok` variant, the
/// expression has the value of the wrapped value.
///
@ -443,3 +509,143 @@ macro_rules! unreachable {
macro_rules! unimplemented {
() => (panic!("not yet implemented"))
}
/// Built-in macros to the compiler itself.
///
/// These macros do not have any corresponding definition with a `macro_rules!`
/// macro, but are documented here. Their implementations can be found hardcoded
/// into libsyntax itself.
///
/// For more information, see documentation for `std`'s macros.
#[cfg(dox)]
pub mod builtin {
/// The core macro for formatted string creation & output.
///
/// For more information, see the documentation for [`std::format_args!`].
///
/// [`std::format_args!`]: ../std/macro.format_args.html
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! format_args { ($fmt:expr, $($args:tt)*) => ({
/* compiler built-in */
}) }
/// Inspect an environment variable at compile time.
///
/// For more information, see the documentation for [`std::env!`].
///
/// [`std::env!`]: ../std/macro.env.html
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! env { ($name:expr) => ({ /* compiler built-in */ }) }
/// Optionally inspect an environment variable at compile time.
///
/// For more information, see the documentation for [`std::option_env!`].
///
/// [`std::option_env!`]: ../std/macro.option_env.html
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! option_env { ($name:expr) => ({ /* compiler built-in */ }) }
/// Concatenate identifiers into one identifier.
///
/// For more information, see the documentation for [`std::concat_idents!`].
///
/// [`std::concat_idents!`]: ../std/macro.concat_idents.html
#[unstable(feature = "concat_idents_macro", issue = "29599")]
#[macro_export]
macro_rules! concat_idents {
($($e:ident),*) => ({ /* compiler built-in */ })
}
/// Concatenates literals into a static string slice.
///
/// For more information, see the documentation for [`std::concat!`].
///
/// [`std::concat!`]: ../std/macro.concat.html
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! concat { ($($e:expr),*) => ({ /* compiler built-in */ }) }
/// A macro which expands to the line number on which it was invoked.
///
/// For more information, see the documentation for [`std::line!`].
///
/// [`std::line!`]: ../std/macro.line.html
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! line { () => ({ /* compiler built-in */ }) }
/// A macro which expands to the column number on which it was invoked.
///
/// For more information, see the documentation for [`std::column!`].
///
/// [`std::column!`]: ../std/macro.column.html
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! column { () => ({ /* compiler built-in */ }) }
/// A macro which expands to the file name from which it was invoked.
///
/// For more information, see the documentation for [`std::file!`].
///
/// [`std::file!`]: ../std/macro.file.html
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! file { () => ({ /* compiler built-in */ }) }
/// A macro which stringifies its argument.
///
/// For more information, see the documentation for [`std::stringify!`].
///
/// [`std::stringify!`]: ../std/macro.stringify.html
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! stringify { ($t:tt) => ({ /* compiler built-in */ }) }
/// Includes a utf8-encoded file as a string.
///
/// For more information, see the documentation for [`std::include_str!`].
///
/// [`std::include_str!`]: ../std/macro.include_str.html
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! include_str { ($file:expr) => ({ /* compiler built-in */ }) }
/// Includes a file as a reference to a byte array.
///
/// For more information, see the documentation for [`std::include_bytes!`].
///
/// [`std::include_bytes!`]: ../std/macro.include_bytes.html
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! include_bytes { ($file:expr) => ({ /* compiler built-in */ }) }
/// Expands to a string that represents the current module path.
///
/// For more information, see the documentation for [`std::module_path!`].
///
/// [`std::module_path!`]: ../std/macro.module_path.html
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! module_path { () => ({ /* compiler built-in */ }) }
/// Boolean evaluation of configuration flags.
///
/// For more information, see the documentation for [`std::cfg!`].
///
/// [`std::cfg!`]: ../std/macro.cfg.html
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) }
/// Parse a file as an expression or an item according to the context.
///
/// For more information, see the documentation for [`std::include!`].
///
/// [`std::include!`]: ../std/macro.include.html
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! include { ($file:expr) => ({ /* compiler built-in */ }) }
}

View file

@ -8,11 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Primitive traits and marker types representing basic 'kinds' of types.
//! Primitive traits and types representing basic properties of types.
//!
//! Rust types can be classified in various useful ways according to
//! intrinsic properties of the type. These classifications, often called
//! 'kinds', are represented as traits.
//! their intrinsic properties. These classifications are represented
//! as traits.
#![stable(feature = "rust1", since = "1.0.0")]
@ -22,7 +22,21 @@ use hash::Hasher;
/// Types that can be transferred across thread boundaries.
///
/// This trait is automatically derived when the compiler determines it's appropriate.
/// This trait is automatically implemented when the compiler determines it's
/// appropriate.
///
/// An example of a non-`Send` type is the reference-counting pointer
/// [`rc::Rc`][rc]. If two threads attempt to clone `Rc`s that point to the same
/// reference-counted value, they might try to update the reference count at the
/// same time, which is [undefined behavior][ub] because `Rc` doesn't use atomic
/// operations. Its cousin [`sync::Arc`][arc] does use atomic operations (incurring
/// some overhead) and thus is `Send`.
///
/// See [the Nomicon](../../nomicon/send-and-sync.html) for more details.
///
/// [rc]: ../../std/rc/struct.Rc.html
/// [arc]: ../../std/sync/struct.Arc.html
/// [ub]: ../../reference.html#behavior-considered-undefined
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
@ -38,10 +52,10 @@ impl<T: ?Sized> !Send for *const T { }
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> !Send for *mut T { }
/// Types with a constant size known at compile-time.
/// Types with a constant size known at compile time.
///
/// All type parameters which can be bounded have an implicit bound of `Sized`. The special syntax
/// `?Sized` can be used to remove this bound if it is not appropriate.
/// All type parameters have an implicit bound of `Sized`. The special syntax
/// `?Sized` can be used to remove this bound if it's not appropriate.
///
/// ```
/// # #![allow(dead_code)]
@ -51,6 +65,26 @@ impl<T: ?Sized> !Send for *mut T { }
/// // struct FooUse(Foo<[i32]>); // error: Sized is not implemented for [i32]
/// struct BarUse(Bar<[i32]>); // OK
/// ```
///
/// The one exception is the implicit `Self` type of a trait, which does not
/// get an implicit `Sized` bound. This is because a `Sized` bound prevents
/// the trait from being used to form a [trait object]:
///
/// ```
/// # #![allow(unused_variables)]
/// trait Foo { }
/// trait Bar: Sized { }
///
/// struct Impl;
/// impl Foo for Impl { }
/// impl Bar for Impl { }
///
/// let x: &Foo = &Impl; // OK
/// // let y: &Bar = &Impl; // error: the trait `Bar` cannot
/// // be made into an object
/// ```
///
/// [trait object]: ../../book/trait-objects.html
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "sized"]
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
@ -59,14 +93,27 @@ pub trait Sized {
// Empty.
}
/// Types that can be "unsized" to a dynamically sized type.
/// Types that can be "unsized" to a dynamically-sized type.
///
/// For example, the sized array type `[i8; 2]` implements `Unsize<[i8]>` and
/// `Unsize<fmt::Debug>`.
///
/// All implementations of `Unsize` are provided automatically by the compiler.
///
/// `Unsize` is used along with [`ops::CoerceUnsized`][coerceunsized] to allow
/// "user-defined" containers such as [`rc::Rc`][rc] to contain dynamically-sized
/// types. See the [DST coercion RFC][RFC982] for more details.
///
/// [coerceunsized]: ../ops/trait.CoerceUnsized.html
/// [rc]: ../../std/rc/struct.Rc.html
/// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
#[unstable(feature = "unsize", issue = "27732")]
#[lang="unsize"]
pub trait Unsize<T: ?Sized> {
// Empty.
}
/// Types that can be copied by simply copying bits (i.e. `memcpy`).
/// Types whose values can be duplicated simply by copying bits.
///
/// By default, variable bindings have 'move semantics.' In other
/// words:
@ -87,7 +134,8 @@ pub trait Unsize<T: ?Sized> {
/// However, if a type implements `Copy`, it instead has 'copy semantics':
///
/// ```
/// // we can just derive a `Copy` implementation
/// // We can derive a `Copy` implementation. `Clone` is also required, as it's
/// // a supertrait of `Copy`.
/// #[derive(Debug, Copy, Clone)]
/// struct Foo;
///
@ -100,13 +148,59 @@ pub trait Unsize<T: ?Sized> {
/// println!("{:?}", x); // A-OK!
/// ```
///
/// It's important to note that in these two examples, the only difference is if you are allowed to
/// access `x` after the assignment: a move is also a bitwise copy under the hood.
/// It's important to note that in these two examples, the only difference is whether you
/// are allowed to access `x` after the assignment. Under the hood, both a copy and a move
/// can result in bits being copied in memory, although this is sometimes optimized away.
///
/// ## How can I implement `Copy`?
///
/// There are two ways to implement `Copy` on your type. The simplest is to use `derive`:
///
/// ```
/// #[derive(Copy, Clone)]
/// struct MyStruct;
/// ```
///
/// You can also implement `Copy` and `Clone` manually:
///
/// ```
/// struct MyStruct;
///
/// impl Copy for MyStruct { }
///
/// impl Clone for MyStruct {
/// fn clone(&self) -> MyStruct {
/// *self
/// }
/// }
/// ```
///
/// There is a small difference between the two: the `derive` strategy will also place a `Copy`
/// bound on type parameters, which isn't always desired.
///
/// ## What's the difference between `Copy` and `Clone`?
///
/// Copies happen implicitly, for example as part of an assignment `y = x`. The behavior of
/// `Copy` is not overloadable; it is always a simple bit-wise copy.
///
/// Cloning is an explicit action, `x.clone()`. The implementation of [`Clone`][clone] can
/// provide any type-specific behavior necessary to duplicate values safely. For example,
/// the implementation of `Clone` for [`String`][string] needs to copy the pointed-to string
/// buffer in the heap. A simple bitwise copy of `String` values would merely copy the
/// pointer, leading to a double free down the line. For this reason, `String` is `Clone`
/// but not `Copy`.
///
/// `Clone` is a supertrait of `Copy`, so everything which is `Copy` must also implement
/// `Clone`. If a type is `Copy` then its `Clone` implementation need only return `*self`
/// (see the example above).
///
/// [clone]: ../clone/trait.Clone.html
/// [string]: ../../std/string/struct.String.html
///
/// ## When can my type be `Copy`?
///
/// A type can implement `Copy` if all of its components implement `Copy`. For example, this
/// `struct` can be `Copy`:
/// struct can be `Copy`:
///
/// ```
/// # #[allow(dead_code)]
@ -116,7 +210,8 @@ pub trait Unsize<T: ?Sized> {
/// }
/// ```
///
/// A `struct` can be `Copy`, and `i32` is `Copy`, so therefore, `Point` is eligible to be `Copy`.
/// A struct can be `Copy`, and `i32` is `Copy`, therefore `Point` is eligible to be `Copy`.
/// By contrast, consider
///
/// ```
/// # #![allow(dead_code)]
@ -126,57 +221,35 @@ pub trait Unsize<T: ?Sized> {
/// }
/// ```
///
/// The `PointList` `struct` cannot implement `Copy`, because [`Vec<T>`] is not `Copy`. If we
/// The struct `PointList` cannot implement `Copy`, because [`Vec<T>`] is not `Copy`. If we
/// attempt to derive a `Copy` implementation, we'll get an error:
///
/// ```text
/// the trait `Copy` may not be implemented for this type; field `points` does not implement `Copy`
/// ```
///
/// ## When can my type _not_ be `Copy`?
/// ## When *can't* my type be `Copy`?
///
/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased
/// mutable reference, and copying [`String`] would result in two attempts to free the same buffer.
/// mutable reference. Copying [`String`] would duplicate responsibility for managing the `String`'s
/// buffer, leading to a double free.
///
/// Generalizing the latter case, any type implementing [`Drop`] can't be `Copy`, because it's
/// managing some resource besides its own [`size_of::<T>()`] bytes.
///
/// ## What if I derive `Copy` on a type that can't?
/// If you try to implement `Copy` on a struct or enum containing non-`Copy` data, you will get a
/// compile-time error. Specifically, with structs you'll get [E0204] and with enums you'll get
/// [E0205].
///
/// If you try to derive `Copy` on a struct or enum, you will get a compile-time error.
/// Specifically, with structs you'll get [E0204](https://doc.rust-lang.org/error-index.html#E0204)
/// and with enums you'll get [E0205](https://doc.rust-lang.org/error-index.html#E0205).
/// [E0204]: https://doc.rust-lang.org/error-index.html#E0204
/// [E0205]: https://doc.rust-lang.org/error-index.html#E0205
///
/// ## When should my type be `Copy`?
/// ## When *should* my type be `Copy`?
///
/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing
/// to consider though: if you think your type may _not_ be able to implement `Copy` in the future,
/// then it might be prudent to not implement `Copy`. This is because removing `Copy` is a breaking
/// change: that second example would fail to compile if we made `Foo` non-`Copy`.
///
/// ## Derivable
///
/// This trait can be used with `#[derive]` if all of its components implement `Copy` and the type.
///
/// ## How can I implement `Copy`?
///
/// There are two ways to implement `Copy` on your type:
///
/// ```
/// #[derive(Copy, Clone)]
/// struct MyStruct;
/// ```
///
/// and
///
/// ```
/// struct MyStruct;
/// impl Copy for MyStruct {}
/// impl Clone for MyStruct { fn clone(&self) -> MyStruct { *self } }
/// ```
///
/// There is a small difference between the two: the `derive` strategy will also place a `Copy`
/// bound on type parameters, which isn't always desired.
/// Generally speaking, if your type _can_ implement `Copy`, it should. Keep in mind, though,
/// that implementing `Copy` is part of the public API of your type. If the type might become
/// non-`Copy` in the future, it could be prudent to omit the `Copy` implementation now, to
/// avoid a breaking API change.
///
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
/// [`String`]: ../../std/string/struct.String.html
@ -188,64 +261,74 @@ pub trait Copy : Clone {
// Empty.
}
/// Types that can be safely shared between threads when aliased.
/// Types for which it is safe to share references between threads.
///
/// This trait is automatically implemented when the compiler determines
/// it's appropriate.
///
/// The precise definition is: a type `T` is `Sync` if `&T` is
/// thread-safe. In other words, there is no possibility of data races
/// when passing `&T` references between threads.
/// [`Send`][send]. In other words, if there is no possibility of
/// [undefined behavior][ub] (including data races) when passing
/// `&T` references between threads.
///
/// As one would expect, primitive types like [`u8`] and [`f64`] are all
/// `Sync`, and so are simple aggregate types containing them (like
/// tuples, structs and enums). More instances of basic `Sync` types
/// include "immutable" types like `&T` and those with simple
/// inherited mutability, such as [`Box<T>`], [`Vec<T>`] and most other
/// collection types. (Generic parameters need to be `Sync` for their
/// container to be `Sync`.)
/// As one would expect, primitive types like [`u8`][u8] and [`f64`][f64]
/// are all `Sync`, and so are simple aggregate types containing them,
/// like tuples, structs and enums. More examples of basic `Sync`
/// types include "immutable" types like `&T`, and those with simple
/// inherited mutability, such as [`Box<T>`][box], [`Vec<T>`][vec] and
/// most other collection types. (Generic parameters need to be `Sync`
/// for their container to be `Sync`.)
///
/// A somewhat surprising consequence of the definition is `&mut T` is
/// `Sync` (if `T` is `Sync`) even though it seems that it might
/// provide unsynchronized mutation. The trick is a mutable reference
/// stored in an aliasable reference (that is, `& &mut T`) becomes
/// read-only, as if it were a `& &T`, hence there is no risk of a data
/// race.
/// A somewhat surprising consequence of the definition is that `&mut T`
/// is `Sync` (if `T` is `Sync`) even though it seems like that might
/// provide unsynchronized mutation. The trick is that a mutable
/// reference behind a shared reference (that is, `& &mut T`)
/// becomes read-only, as if it were a `& &T`. Hence there is no risk
/// of a data race.
///
/// Types that are not `Sync` are those that have "interior
/// mutability" in a non-thread-safe way, such as [`Cell`] and [`RefCell`]
/// in [`std::cell`]. These types allow for mutation of their contents
/// even when in an immutable, aliasable slot, e.g. the contents of
/// [`&Cell<T>`][`Cell`] can be [`.set`], and do not ensure data races are
/// impossible, hence they cannot be `Sync`. A higher level example
/// of a non-`Sync` type is the reference counted pointer
/// [`std::rc::Rc`][`Rc`], because any reference [`&Rc<T>`][`Rc`] can clone a new
/// reference, which modifies the reference counts in a non-atomic
/// way.
/// mutability" in a non-thread-safe form, such as [`cell::Cell`][cell]
/// and [`cell::RefCell`][refcell]. These types allow for mutation of
/// their contents even through an immutable, shared reference. For
/// example the `set` method on `Cell<T>` takes `&self`, so it requires
/// only a shared reference `&Cell<T>`. The method performs no
/// synchronization, thus `Cell` cannot be `Sync`.
///
/// Another example of a non-`Sync` type is the reference-counting
/// pointer [`rc::Rc`][rc]. Given any reference `&Rc<T>`, you can clone
/// a new `Rc<T>`, modifying the reference counts in a non-atomic way.
///
/// For cases when one does need thread-safe interior mutability,
/// types like the atomics in [`std::sync`][`sync`] and [`Mutex`] / [`RwLock`] in
/// the [`sync`] crate do ensure that any mutation cannot cause data
/// races. Hence these types are `Sync`.
/// Rust provides [atomic data types], as well as explicit locking via
/// [`sync::Mutex`][mutex] and [`sync::RWLock`][rwlock]. These types
/// ensure that any mutation cannot cause data races, hence the types
/// are `Sync`. Likewise, [`sync::Arc`][arc] provides a thread-safe
/// analogue of `Rc`.
///
/// Any types with interior mutability must also use the [`std::cell::UnsafeCell`]
/// wrapper around the value(s) which can be mutated when behind a `&`
/// reference; not doing this is undefined behavior (for example,
/// [`transmute`]-ing from `&T` to `&mut T` is invalid).
/// Any types with interior mutability must also use the
/// [`cell::UnsafeCell`][unsafecell] wrapper around the value(s) which
/// can be mutated through a shared reference. Failing to doing this is
/// [undefined behavior][ub]. For example, [`transmute`][transmute]-ing
/// from `&T` to `&mut T` is invalid.
///
/// This trait is automatically derived when the compiler determines it's appropriate.
/// See [the Nomicon](../../nomicon/send-and-sync.html) for more
/// details about `Sync`.
///
/// [`u8`]: ../../std/primitive.u8.html
/// [`f64`]: ../../std/primitive.f64.html
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
/// [`Box<T>`]: ../../std/boxed/struct.Box.html
/// [`Cell`]: ../../std/cell/struct.Cell.html
/// [`RefCell`]: ../../std/cell/struct.RefCell.html
/// [`std::cell`]: ../../std/cell/index.html
/// [`.set`]: ../../std/cell/struct.Cell.html#method.set
/// [`Rc`]: ../../std/rc/struct.Rc.html
/// [`sync`]: ../../std/sync/index.html
/// [`Mutex`]: ../../std/sync/struct.Mutex.html
/// [`RwLock`]: ../../std/sync/struct.RwLock.html
/// [`std::cell::UnsafeCell`]: ../../std/cell/struct.UnsafeCell.html
/// [`transmute`]: ../../std/mem/fn.transmute.html
/// [send]: trait.Send.html
/// [u8]: ../../std/primitive.u8.html
/// [f64]: ../../std/primitive.f64.html
/// [box]: ../../std/boxed/struct.Box.html
/// [vec]: ../../std/vec/struct.Vec.html
/// [cell]: ../cell/struct.Cell.html
/// [refcell]: ../cell/struct.RefCell.html
/// [rc]: ../../std/rc/struct.Rc.html
/// [arc]: ../../std/sync/struct.Arc.html
/// [atomic data types]: ../sync/atomic/index.html
/// [mutex]: ../../std/sync/struct.Mutex.html
/// [rwlock]: ../../std/sync/struct.RwLock.html
/// [unsafecell]: ../cell/struct.UnsafeCell.html
/// [ub]: ../../reference.html#behavior-considered-undefined
/// [transmute]: ../../std/mem/fn.transmute.html
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
@ -314,29 +397,30 @@ macro_rules! impls{
)
}
/// `PhantomData<T>` allows you to describe that a type acts as if it stores a value of type `T`,
/// even though it does not. This allows you to inform the compiler about certain safety properties
/// of your code.
/// Zero-sized type used to mark things that "act like" they own a `T`.
///
/// For a more in-depth explanation of how to use `PhantomData<T>`, please see [the Nomicon].
/// Adding a `PhantomData<T>` field to your type tells the compiler that your
/// type acts as though it stores a value of type `T`, even though it doesn't
/// really. This information is used when computing certain safety properties.
///
/// [the Nomicon]: ../../nomicon/phantom-data.html
/// For a more in-depth explanation of how to use `PhantomData<T>`, please see
/// [the Nomicon](../../nomicon/phantom-data.html).
///
/// # A ghastly note 👻👻👻
///
/// Though they both have scary names, `PhantomData<T>` and 'phantom types' are related, but not
/// identical. Phantom types are a more general concept that don't require `PhantomData<T>` to
/// implement, but `PhantomData<T>` is the most common way to implement them in a correct manner.
/// Though they both have scary names, `PhantomData` and 'phantom types' are
/// related, but not identical. A phantom type parameter is simply a type
/// parameter which is never used. In Rust, this often causes the compiler to
/// complain, and the solution is to add a "dummy" use by way of `PhantomData`.
///
/// # Examples
///
/// ## Unused lifetime parameter
/// ## Unused lifetime parameters
///
/// Perhaps the most common time that `PhantomData` is required is
/// with a struct that has an unused lifetime parameter, typically as
/// part of some unsafe code. For example, here is a struct `Slice`
/// that has two pointers of type `*const T`, presumably pointing into
/// an array somewhere:
/// Perhaps the most common use case for `PhantomData` is a struct that has an
/// unused lifetime parameter, typically as part of some unsafe code. For
/// example, here is a struct `Slice` that has two pointers of type `*const T`,
/// presumably pointing into an array somewhere:
///
/// ```ignore
/// struct Slice<'a, T> {
@ -350,7 +434,7 @@ macro_rules! impls{
/// intent is not expressed in the code, since there are no uses of
/// the lifetime `'a` and hence it is not clear what data it applies
/// to. We can correct this by telling the compiler to act *as if* the
/// `Slice` struct contained a borrowed reference `&'a T`:
/// `Slice` struct contained a reference `&'a T`:
///
/// ```
/// use std::marker::PhantomData;
@ -359,29 +443,53 @@ macro_rules! impls{
/// struct Slice<'a, T: 'a> {
/// start: *const T,
/// end: *const T,
/// phantom: PhantomData<&'a T>
/// phantom: PhantomData<&'a T>,
/// }
/// ```
///
/// This also in turn requires that we annotate `T:'a`, indicating
/// that `T` is a type that can be borrowed for the lifetime `'a`.
/// This also in turn requires the annotation `T: 'a`, indicating
/// that any references in `T` are valid over the lifetime `'a`.
///
/// ## Unused type parameters
///
/// It sometimes happens that there are unused type parameters that
/// indicate what type of data a struct is "tied" to, even though that
/// data is not actually found in the struct itself. Here is an
/// example where this arises when handling external resources over a
/// foreign function interface. `PhantomData<T>` can prevent
/// mismatches by enforcing types in the method implementations:
/// When initializing a `Slice` you simply provide the value
/// `PhantomData` for the field `phantom`:
///
/// ```
/// # #![allow(dead_code)]
/// # trait ResType { fn foo(&self); }
/// # use std::marker::PhantomData;
/// # struct Slice<'a, T: 'a> {
/// # start: *const T,
/// # end: *const T,
/// # phantom: PhantomData<&'a T>,
/// # }
/// fn borrow_vec<'a, T>(vec: &'a Vec<T>) -> Slice<'a, T> {
/// let ptr = vec.as_ptr();
/// Slice {
/// start: ptr,
/// end: unsafe { ptr.offset(vec.len() as isize) },
/// phantom: PhantomData,
/// }
/// }
/// ```
///
/// ## Unused type parameters
///
/// It sometimes happens that you have unused type parameters which
/// indicate what type of data a struct is "tied" to, even though that
/// data is not actually found in the struct itself. Here is an
/// example where this arises with [FFI]. The foreign interface uses
/// handles of type `*mut ()` to refer to Rust values of different
/// types. We track the Rust type using a phantom type parameter on
/// the struct `ExternalResource` which wraps a handle.
///
/// [FFI]: ../../book/ffi.html
///
/// ```
/// # #![allow(dead_code)]
/// # trait ResType { }
/// # struct ParamType;
/// # mod foreign_lib {
/// # pub fn new(_: usize) -> *mut () { 42 as *mut () }
/// # pub fn do_stuff(_: *mut (), _: usize) {}
/// # pub fn new(_: usize) -> *mut () { 42 as *mut () }
/// # pub fn do_stuff(_: *mut (), _: usize) {}
/// # }
/// # fn convert_params(_: ParamType) -> usize { 42 }
/// use std::marker::PhantomData;
@ -408,21 +516,20 @@ macro_rules! impls{
/// }
/// ```
///
/// ## Indicating ownership
/// ## Ownership and the drop check
///
/// Adding a field of type `PhantomData<T>` also indicates that your
/// struct owns data of type `T`. This in turn implies that when your
/// struct is dropped, it may in turn drop one or more instances of
/// the type `T`, though that may not be apparent from the other
/// structure of the type itself. This is commonly necessary if the
/// structure is using a raw pointer like `*mut T` whose referent
/// may be dropped when the type is dropped, as a `*mut T` is
/// otherwise not treated as owned.
/// Adding a field of type `PhantomData<T>` indicates that your
/// type owns data of type `T`. This in turn implies that when your
/// type is dropped, it may drop one or more instances of the type
/// `T`. This has bearing on the Rust compiler's [drop check]
/// analysis.
///
/// If your struct does not in fact *own* the data of type `T`, it is
/// better to use a reference type, like `PhantomData<&'a T>`
/// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so
/// as not to indicate ownership.
///
/// [drop check]: ../../nomicon/dropck.html
#[lang = "phantom_data"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct PhantomData<T:?Sized>;
@ -438,10 +545,13 @@ mod impls {
/// Types that can be reflected over.
///
/// This trait is implemented for all types. Its purpose is to ensure
/// that when you write a generic function that will employ
/// reflection, that must be reflected (no pun intended) in the
/// generic bounds of that function. Here is an example:
/// By "reflection" we mean use of the [`Any`][any] trait, or related
/// machinery such as [`TypeId`][typeid].
///
/// `Reflect` is implemented for all types. Its purpose is to ensure
/// that when you write a generic function that will employ reflection,
/// that must be reflected (no pun intended) in the generic bounds of
/// that function.
///
/// ```
/// #![feature(reflect_marker)]
@ -455,25 +565,29 @@ mod impls {
/// }
/// ```
///
/// Without the declaration `T: Reflect`, `foo` would not type check
/// (note: as a matter of style, it would be preferable to write
/// `T: Any`, because `T: Any` implies `T: Reflect` and `T: 'static`, but
/// we use `Reflect` here to show how it works). The `Reflect` bound
/// thus serves to alert `foo`'s caller to the fact that `foo` may
/// behave differently depending on whether `T = u32` or not. In
/// particular, thanks to the `Reflect` bound, callers know that a
/// function declared like `fn bar<T>(...)` will always act in
/// precisely the same way no matter what type `T` is supplied,
/// because there are no bounds declared on `T`. (The ability for a
/// caller to reason about what a function may do based solely on what
/// generic bounds are declared is often called the ["parametricity
/// property"][1].)
/// Without the bound `T: Reflect`, `foo` would not typecheck. (As
/// a matter of style, it would be preferable to write `T: Any`,
/// because `T: Any` implies `T: Reflect` and `T: 'static`, but we
/// use `Reflect` here for illustrative purposes.)
///
/// [1]: http://en.wikipedia.org/wiki/Parametricity
/// The `Reflect` bound serves to alert `foo`'s caller to the
/// fact that `foo` may behave differently depending on whether
/// `T` is `u32` or not. The ability for a caller to reason about what
/// a function may do based solely on what generic bounds are declared
/// is often called the "[parametricity property][param]". Despite the
/// use of `Reflect`, Rust lacks true parametricity because a generic
/// function can, at the very least, call [`mem::size_of`][size_of]
/// without employing any trait bounds whatsoever.
///
/// [any]: ../any/trait.Any.html
/// [typeid]: ../any/struct.TypeId.html
/// [param]: http://en.wikipedia.org/wiki/Parametricity
/// [size_of]: ../mem/fn.size_of.html
#[rustc_reflect_like]
#[unstable(feature = "reflect_marker",
reason = "requires RFC and more experience",
issue = "27749")]
#[rustc_deprecated(since = "1.14.0", reason = "Specialization makes parametricity impossible")]
#[rustc_on_unimplemented = "`{Self}` does not implement `Any`; \
ensure all type parameters are bounded by `Any`"]
pub trait Reflect {}
@ -481,4 +595,6 @@ pub trait Reflect {}
#[unstable(feature = "reflect_marker",
reason = "requires RFC and more experience",
issue = "27749")]
#[rustc_deprecated(since = "1.14.0", reason = "Specialization makes parametricity impossible")]
#[allow(deprecated)]
impl Reflect for .. { }

Some files were not shown because too many files have changed in this diff Show more