Merge branch 'master' of git://github.com/rust-lang/rust
* 'master' of git://github.com/rust-lang/rust: (70 commits) sanitizer-dylib: only run where std for x86_64-linux is available travis: Fix build order of dist-x86-linux fix the sanitizer-dylib test on non x86_64 linux hosts dist-x86-linux: install newer kernel headers enable sanitizers on build job that tests x86_64 linux enable sanitizers on x86_64-linux releases use helper function in the rebuild logic of the rustc_*san crates build/test the sanitizers only when --enable-sanitizers is used sanitizer support Add missing urls on join_paths Add test for #27433 Add more examples, get everything passing at last. Remove some leftover makefiles. Add more test for rustdoc --test Rename manifest_version to manifest-version reference: clarify #[cfg] section Bump stable release date rustbuild: Clean build/dist on `make clean` Add missing urls for current_dir review nits ...
This commit is contained in:
commit
ec73ef9dc8
303 changed files with 7876 additions and 10388 deletions
73
src/Cargo.lock
generated
73
src/Cargo.lock
generated
|
|
@ -19,7 +19,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"build_helper 0.1.0",
|
||||
"core 0.0.0",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.0.0",
|
||||
]
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ dependencies = [
|
|||
"build_helper 0.1.0",
|
||||
"cmake 0.1.18 (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.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
@ -74,7 +74,7 @@ name = "cmake"
|
|||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -91,7 +91,7 @@ name = "compiler_builtins"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"core 0.0.0",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -99,6 +99,7 @@ name = "compiletest"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
|
@ -132,7 +133,7 @@ name = "flate"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"build_helper 0.1.0",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -141,7 +142,7 @@ version = "0.0.0"
|
|||
|
||||
[[package]]
|
||||
name = "gcc"
|
||||
version = "0.3.40"
|
||||
version = "0.3.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
|
@ -224,6 +225,14 @@ dependencies = [
|
|||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qemu-test-client"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "qemu-test-server"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.0.0"
|
||||
|
|
@ -268,6 +277,16 @@ name = "rustc-serialize"
|
|||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_asan"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc_system 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_back"
|
||||
version = "0.0.0"
|
||||
|
|
@ -397,10 +416,20 @@ name = "rustc_llvm"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"build_helper 0.1.0",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_bitflags 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_lsan"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc_system 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_metadata"
|
||||
version = "0.0.0"
|
||||
|
|
@ -435,6 +464,16 @@ dependencies = [
|
|||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_msan"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc_system 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_passes"
|
||||
version = "0.0.0"
|
||||
|
|
@ -516,6 +555,16 @@ dependencies = [
|
|||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_tsan"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc_system 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_typeck"
|
||||
version = "0.0.0"
|
||||
|
|
@ -540,7 +589,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"arena 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.0.0",
|
||||
"rustc 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
|
|
@ -572,11 +621,15 @@ dependencies = [
|
|||
"collections 0.0.0",
|
||||
"compiler_builtins 0.0.0",
|
||||
"core 0.0.0",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.43 (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_asan 0.0.0",
|
||||
"rustc_lsan 0.0.0",
|
||||
"rustc_msan 0.0.0",
|
||||
"rustc_tsan 0.0.0",
|
||||
"std_unicode 0.0.0",
|
||||
"unwind 0.0.0",
|
||||
]
|
||||
|
|
@ -662,7 +715,7 @@ dependencies = [
|
|||
"checksum cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0e5bcf27e097a184c1df4437654ed98df3d7a516e8508a6ba45d8b092bbdf283"
|
||||
"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.40 (registry+https://github.com/rust-lang/crates.io-index)" = "872db9e59486ef2b14f8e8c10e9ef02de2bccef6363d7f34835dedb386b3d950"
|
||||
"checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d"
|
||||
"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
|
||||
"checksum 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"
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ members = [
|
|||
"tools/rustbook",
|
||||
"tools/tidy",
|
||||
"tools/build-manifest",
|
||||
"tools/qemu-test-client",
|
||||
"tools/qemu-test-server",
|
||||
]
|
||||
|
||||
# Curiously, compiletest will segfault if compiled with opt-level=3 on 64-bit
|
||||
|
|
|
|||
|
|
@ -15,55 +15,45 @@
|
|||
//! `package_vers`, and otherwise indicating to the compiler what it should
|
||||
//! print out as part of its version information.
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::process::Command;
|
||||
|
||||
use build_helper::output;
|
||||
|
||||
use Build;
|
||||
|
||||
pub fn collect(build: &mut Build) {
|
||||
// Currently the canonical source for the release number (e.g. 1.10.0) and
|
||||
// the prerelease version (e.g. `.1`) is in `mk/main.mk`. We "parse" that
|
||||
// here to learn about those numbers.
|
||||
let mut main_mk = String::new();
|
||||
t!(t!(File::open(build.src.join("mk/main.mk"))).read_to_string(&mut main_mk));
|
||||
let mut release_num = "";
|
||||
let mut prerelease_version = "";
|
||||
for line in main_mk.lines() {
|
||||
if line.starts_with("CFG_RELEASE_NUM") {
|
||||
release_num = line.split('=').skip(1).next().unwrap().trim();
|
||||
}
|
||||
if line.starts_with("CFG_PRERELEASE_VERSION") {
|
||||
prerelease_version = line.split('=').skip(1).next().unwrap().trim();
|
||||
}
|
||||
}
|
||||
// The version number
|
||||
const CFG_RELEASE_NUM: &'static str = "1.17.0";
|
||||
|
||||
build.release_num = release_num.to_string();
|
||||
build.prerelease_version = release_num.to_string();
|
||||
// An optional number to put after the label, e.g. '.2' -> '-beta.2'
|
||||
// Be sure to make this starts with a dot to conform to semver pre-release
|
||||
// versions (section 9)
|
||||
const CFG_PRERELEASE_VERSION: &'static str = ".1";
|
||||
|
||||
pub fn collect(build: &mut Build) {
|
||||
build.release_num = CFG_RELEASE_NUM.to_string();
|
||||
build.prerelease_version = CFG_RELEASE_NUM.to_string();
|
||||
|
||||
// Depending on the channel, passed in `./configure --release-channel`,
|
||||
// determine various properties of the build.
|
||||
match &build.config.channel[..] {
|
||||
"stable" => {
|
||||
build.release = release_num.to_string();
|
||||
build.release = CFG_RELEASE_NUM.to_string();
|
||||
build.package_vers = build.release.clone();
|
||||
build.unstable_features = false;
|
||||
}
|
||||
"beta" => {
|
||||
build.release = format!("{}-beta{}", release_num,
|
||||
prerelease_version);
|
||||
build.release = format!("{}-beta{}", CFG_RELEASE_NUM,
|
||||
CFG_PRERELEASE_VERSION);
|
||||
build.package_vers = "beta".to_string();
|
||||
build.unstable_features = false;
|
||||
}
|
||||
"nightly" => {
|
||||
build.release = format!("{}-nightly", release_num);
|
||||
build.release = format!("{}-nightly", CFG_RELEASE_NUM);
|
||||
build.package_vers = "nightly".to_string();
|
||||
build.unstable_features = true;
|
||||
}
|
||||
_ => {
|
||||
build.release = format!("{}-dev", release_num);
|
||||
build.release = format!("{}-dev", CFG_RELEASE_NUM);
|
||||
build.package_vers = build.release.clone();
|
||||
build.unstable_features = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ use build_helper::output;
|
|||
|
||||
use {Build, Compiler, Mode};
|
||||
use dist;
|
||||
use util::{self, dylib_path, dylib_path_var};
|
||||
use util::{self, dylib_path, dylib_path_var, exe};
|
||||
|
||||
const ADB_TEST_DIR: &'static str = "/data/tmp";
|
||||
|
||||
|
|
@ -221,6 +221,12 @@ pub fn compiletest(build: &Build,
|
|||
.arg("--llvm-cxxflags").arg("");
|
||||
}
|
||||
|
||||
if build.qemu_rootfs(target).is_some() {
|
||||
cmd.arg("--qemu-test-client")
|
||||
.arg(build.tool(&Compiler::new(0, &build.config.build),
|
||||
"qemu-test-client"));
|
||||
}
|
||||
|
||||
// Running a C compiler on MSVC requires a few env vars to be set, to be
|
||||
// sure to set them here.
|
||||
//
|
||||
|
|
@ -236,6 +242,10 @@ pub fn compiletest(build: &Build,
|
|||
cmd.env("RUSTC_BOOTSTRAP", "1");
|
||||
build.add_rust_test_threads(&mut cmd);
|
||||
|
||||
if build.config.sanitizers {
|
||||
cmd.env("SANITIZER_SUPPORT", "1");
|
||||
}
|
||||
|
||||
cmd.arg("--adb-path").arg("adb");
|
||||
cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
|
||||
if target.contains("android") {
|
||||
|
|
@ -403,9 +413,9 @@ pub fn krate(build: &Build,
|
|||
dylib_path.insert(0, build.sysroot_libdir(&compiler, target));
|
||||
cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
|
||||
|
||||
if target.contains("android") {
|
||||
cargo.arg("--no-run");
|
||||
} else if target.contains("emscripten") {
|
||||
if target.contains("android") ||
|
||||
target.contains("emscripten") ||
|
||||
build.qemu_rootfs(target).is_some() {
|
||||
cargo.arg("--no-run");
|
||||
}
|
||||
|
||||
|
|
@ -423,6 +433,9 @@ pub fn krate(build: &Build,
|
|||
} else if target.contains("emscripten") {
|
||||
build.run(&mut cargo);
|
||||
krate_emscripten(build, &compiler, target, mode);
|
||||
} else if build.qemu_rootfs(target).is_some() {
|
||||
build.run(&mut cargo);
|
||||
krate_qemu(build, &compiler, target, mode);
|
||||
} else {
|
||||
cargo.args(&build.flags.cmd.test_args());
|
||||
build.run(&mut cargo);
|
||||
|
|
@ -480,23 +493,46 @@ 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);
|
||||
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 mut cmd = Command::new(nodejs);
|
||||
cmd.arg(&test_file_name);
|
||||
if build.config.quiet_tests {
|
||||
cmd.arg("--quiet");
|
||||
}
|
||||
build.run(&mut cmd);
|
||||
}
|
||||
}
|
||||
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 mut cmd = Command::new(nodejs);
|
||||
cmd.arg(&test_file_name);
|
||||
if build.config.quiet_tests {
|
||||
cmd.arg("--quiet");
|
||||
}
|
||||
build.run(&mut cmd);
|
||||
}
|
||||
}
|
||||
|
||||
fn krate_qemu(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);
|
||||
|
||||
let tool = build.tool(&Compiler::new(0, &build.config.build),
|
||||
"qemu-test-client");
|
||||
for test in tests {
|
||||
let mut cmd = Command::new(&tool);
|
||||
cmd.arg("run")
|
||||
.arg(&test);
|
||||
if build.config.quiet_tests {
|
||||
cmd.arg("--quiet");
|
||||
}
|
||||
cmd.args(&build.flags.cmd.test_args());
|
||||
build.run(&mut cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn find_tests(dir: &Path,
|
||||
|
|
@ -516,13 +552,15 @@ fn find_tests(dir: &Path,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn android_copy_libs(build: &Build,
|
||||
compiler: &Compiler,
|
||||
target: &str) {
|
||||
if !target.contains("android") {
|
||||
return
|
||||
pub fn emulator_copy_libs(build: &Build, compiler: &Compiler, target: &str) {
|
||||
if target.contains("android") {
|
||||
android_copy_libs(build, compiler, target)
|
||||
} else if let Some(s) = build.qemu_rootfs(target) {
|
||||
qemu_copy_libs(build, compiler, target, s)
|
||||
}
|
||||
}
|
||||
|
||||
fn android_copy_libs(build: &Build, compiler: &Compiler, target: &str) {
|
||||
println!("Android copy libs to emulator ({})", target);
|
||||
build.run(Command::new("adb").arg("wait-for-device"));
|
||||
build.run(Command::new("adb").arg("remount"));
|
||||
|
|
@ -548,6 +586,39 @@ pub fn android_copy_libs(build: &Build,
|
|||
}
|
||||
}
|
||||
|
||||
fn qemu_copy_libs(build: &Build,
|
||||
compiler: &Compiler,
|
||||
target: &str,
|
||||
rootfs: &Path) {
|
||||
println!("QEMU copy libs to emulator ({})", target);
|
||||
assert!(target.starts_with("arm"), "only works with arm for now");
|
||||
t!(fs::create_dir_all(build.out.join("tmp")));
|
||||
|
||||
// Copy our freshly compiled test server over to the rootfs
|
||||
let server = build.cargo_out(compiler, Mode::Tool, target)
|
||||
.join(exe("qemu-test-server", target));
|
||||
t!(fs::copy(&server, rootfs.join("testd")));
|
||||
|
||||
// Spawn the emulator and wait for it to come online
|
||||
let tool = build.tool(&Compiler::new(0, &build.config.build),
|
||||
"qemu-test-client");
|
||||
build.run(Command::new(&tool)
|
||||
.arg("spawn-emulator")
|
||||
.arg(rootfs)
|
||||
.arg(build.out.join("tmp")));
|
||||
|
||||
// Push all our dylibs to the emulator
|
||||
for f in t!(build.sysroot_libdir(compiler, target).read_dir()) {
|
||||
let f = t!(f);
|
||||
let name = f.file_name().into_string().unwrap();
|
||||
if util::is_dylib(&name) {
|
||||
build.run(Command::new(&tool)
|
||||
.arg("push")
|
||||
.arg(f.path()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Run "distcheck", a 'make check' from a tarball
|
||||
pub fn distcheck(build: &Build) {
|
||||
if build.config.build != "x86_64-unknown-linux-gnu" {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ use Build;
|
|||
pub fn clean(build: &Build) {
|
||||
rm_rf(build, "tmp".as_ref());
|
||||
rm_rf(build, &build.out.join("tmp"));
|
||||
rm_rf(build, &build.out.join("dist"));
|
||||
|
||||
for host in build.config.host.iter() {
|
||||
let entries = match build.out.join(host).read_dir() {
|
||||
|
|
|
|||
|
|
@ -51,6 +51,17 @@ pub fn std(build: &Build, target: &str, compiler: &Compiler) {
|
|||
if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc {
|
||||
features.push_str(" force_alloc_system");
|
||||
}
|
||||
|
||||
if compiler.stage != 0 && build.config.sanitizers {
|
||||
// This variable is used by the sanitizer runtime crates, e.g.
|
||||
// rustc_lsan, to build the sanitizer runtime from C code
|
||||
// When this variable is missing, those crates won't compile the C code,
|
||||
// so we don't set this variable during stage0 where llvm-config is
|
||||
// missing
|
||||
// We also only build the runtimes when --enable-sanitizers (or its
|
||||
// config.toml equivalent) is used
|
||||
cargo.env("LLVM_CONFIG", build.llvm_config(target));
|
||||
}
|
||||
cargo.arg("--features").arg(features)
|
||||
.arg("--manifest-path")
|
||||
.arg(build.src.join("src/rustc/std_shim/Cargo.toml"));
|
||||
|
|
@ -382,10 +393,10 @@ fn add_to_sysroot(out_dir: &Path, sysroot_dst: &Path) {
|
|||
///
|
||||
/// This will build the specified tool with the specified `host` compiler in
|
||||
/// `stage` into the normal cargo output directory.
|
||||
pub fn tool(build: &Build, stage: u32, host: &str, tool: &str) {
|
||||
println!("Building stage{} tool {} ({})", stage, tool, host);
|
||||
pub fn tool(build: &Build, stage: u32, target: &str, tool: &str) {
|
||||
println!("Building stage{} tool {} ({})", stage, tool, target);
|
||||
|
||||
let compiler = Compiler::new(stage, host);
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
|
||||
// FIXME: need to clear out previous tool and ideally deps, may require
|
||||
// isolating output directories or require a pseudo shim step to
|
||||
|
|
@ -396,7 +407,7 @@ pub fn tool(build: &Build, stage: u32, host: &str, tool: &str) {
|
|||
// let out_dir = build.cargo_out(stage, &host, Mode::Librustc, target);
|
||||
// build.clear_if_dirty(&out_dir, &libstd_stamp(build, stage, &host, target));
|
||||
|
||||
let mut cargo = build.cargo(&compiler, Mode::Tool, host, "build");
|
||||
let mut cargo = build.cargo(&compiler, Mode::Tool, target, "build");
|
||||
cargo.arg("--manifest-path")
|
||||
.arg(build.src.join(format!("src/tools/{}/Cargo.toml", tool)));
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ pub struct Config {
|
|||
pub target_config: HashMap<String, Target>,
|
||||
pub full_bootstrap: bool,
|
||||
pub extended: bool,
|
||||
pub sanitizers: bool,
|
||||
|
||||
// llvm codegen options
|
||||
pub llvm_assertions: bool,
|
||||
|
|
@ -114,6 +115,7 @@ pub struct Target {
|
|||
pub cxx: Option<PathBuf>,
|
||||
pub ndk: Option<PathBuf>,
|
||||
pub musl_root: Option<PathBuf>,
|
||||
pub qemu_rootfs: Option<PathBuf>,
|
||||
}
|
||||
|
||||
/// Structure of the `config.toml` file that configuration is read from.
|
||||
|
|
@ -149,6 +151,7 @@ struct Build {
|
|||
full_bootstrap: Option<bool>,
|
||||
extended: Option<bool>,
|
||||
verbose: Option<usize>,
|
||||
sanitizers: Option<bool>,
|
||||
}
|
||||
|
||||
/// TOML representation of various global install decisions.
|
||||
|
|
@ -223,6 +226,7 @@ struct TomlTarget {
|
|||
cxx: Option<String>,
|
||||
android_ndk: Option<String>,
|
||||
musl_root: Option<String>,
|
||||
qemu_rootfs: Option<String>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
|
|
@ -294,6 +298,7 @@ impl Config {
|
|||
set(&mut config.full_bootstrap, build.full_bootstrap);
|
||||
set(&mut config.extended, build.extended);
|
||||
set(&mut config.verbose, build.verbose);
|
||||
set(&mut config.sanitizers, build.sanitizers);
|
||||
|
||||
if let Some(ref install) = toml.install {
|
||||
config.prefix = install.prefix.clone().map(PathBuf::from);
|
||||
|
|
@ -362,6 +367,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);
|
||||
target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from);
|
||||
|
||||
config.target_config.insert(triple.clone(), target);
|
||||
}
|
||||
|
|
@ -437,6 +443,7 @@ impl Config {
|
|||
("VENDOR", self.vendor),
|
||||
("FULL_BOOTSTRAP", self.full_bootstrap),
|
||||
("EXTENDED", self.extended),
|
||||
("SANITIZERS", self.sanitizers),
|
||||
}
|
||||
|
||||
match key {
|
||||
|
|
@ -564,6 +571,12 @@ impl Config {
|
|||
.map(|s| s.to_string())
|
||||
.collect();
|
||||
}
|
||||
"CFG_QEMU_ARMHF_ROOTFS" if value.len() > 0 => {
|
||||
let target = "arm-unknown-linux-gnueabihf".to_string();
|
||||
let target = self.target_config.entry(target)
|
||||
.or_insert(Target::default());
|
||||
target.qemu_rootfs = Some(parse_configure_path(value));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,6 +127,9 @@
|
|||
# Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
|
||||
#verbose = 0
|
||||
|
||||
# Build the sanitizer runtimes
|
||||
#sanitizers = false
|
||||
|
||||
# =============================================================================
|
||||
# General install configuration options
|
||||
# =============================================================================
|
||||
|
|
|
|||
|
|
@ -381,13 +381,11 @@ pub fn rust_src(build: &Build) {
|
|||
"README.md",
|
||||
"RELEASES.md",
|
||||
"configure",
|
||||
"Makefile.in",
|
||||
"x.py",
|
||||
];
|
||||
let src_dirs = [
|
||||
"man",
|
||||
"src",
|
||||
"mk"
|
||||
];
|
||||
|
||||
let filter_fn = move |path: &Path| {
|
||||
|
|
@ -517,9 +515,7 @@ pub fn cargo(build: &Build, stage: u32, target: &str) {
|
|||
|
||||
let branch = match &build.config.channel[..] {
|
||||
"stable" |
|
||||
"beta" => {
|
||||
build.release.split(".").take(2).collect::<Vec<_>>().join(".")
|
||||
}
|
||||
"beta" => format!("rust-{}", build.release_num),
|
||||
_ => "master".to_string(),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -599,7 +599,8 @@ impl Build {
|
|||
/// Get the space-separated set of activated features for the standard
|
||||
/// library.
|
||||
fn std_features(&self) -> String {
|
||||
let mut features = "panic-unwind".to_string();
|
||||
let mut features = "panic-unwind asan lsan msan tsan".to_string();
|
||||
|
||||
if self.config.debug_jemalloc {
|
||||
features.push_str(" debug-jemalloc");
|
||||
}
|
||||
|
|
@ -878,6 +879,17 @@ impl Build {
|
|||
.map(|p| &**p)
|
||||
}
|
||||
|
||||
/// Returns the root of the "rootfs" image that this target will be using,
|
||||
/// if one was configured.
|
||||
///
|
||||
/// If `Some` is returned then that means that tests for this target are
|
||||
/// emulated with QEMU and binaries will need to be shipped to the emulator.
|
||||
fn qemu_rootfs(&self, target: &str) -> Option<&Path> {
|
||||
self.config.target_config.get(target)
|
||||
.and_then(|t| t.qemu_rootfs.as_ref())
|
||||
.map(|p| &**p)
|
||||
}
|
||||
|
||||
/// Path to the python interpreter to use
|
||||
fn python(&self) -> &Path {
|
||||
self.config.python.as_ref().unwrap()
|
||||
|
|
|
|||
|
|
@ -9,11 +9,12 @@
|
|||
# except according to those terms.
|
||||
|
||||
include config.mk
|
||||
include $(CFG_SRC_DIR)mk/util.mk
|
||||
|
||||
ifdef VERBOSE
|
||||
Q :=
|
||||
BOOTSTRAP_ARGS := -v
|
||||
else
|
||||
Q := @
|
||||
BOOTSTRAP_ARGS :=
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
|||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
|
||||
.dep(|s| s.name("test-helpers"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.dep(|s| s.name("emulator-copy-libs"))
|
||||
.default(mode != "pretty") // pretty tests don't run everywhere
|
||||
.run(move |s| {
|
||||
check::compiletest(build, &s.compiler(), s.target, mode, dir)
|
||||
|
|
@ -333,7 +333,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
|||
.dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
|
||||
.dep(|s| s.name("test-helpers"))
|
||||
.dep(|s| s.name("debugger-scripts"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.dep(|s| s.name("emulator-copy-libs"))
|
||||
.run(move |s| check::compiletest(build, &s.compiler(), s.target,
|
||||
"debuginfo-gdb", "debuginfo"));
|
||||
let mut rule = rules.test("check-debuginfo", "src/test/debuginfo");
|
||||
|
|
@ -387,14 +387,14 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
|||
for (krate, path, _default) in krates("std_shim") {
|
||||
rules.test(&krate.test_step, path)
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.dep(|s| s.name("emulator-copy-libs"))
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
Mode::Libstd, TestKind::Test,
|
||||
Some(&krate.name)));
|
||||
}
|
||||
rules.test("check-std-all", "path/to/nowhere")
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.dep(|s| s.name("emulator-copy-libs"))
|
||||
.default(true)
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
Mode::Libstd, TestKind::Test, None));
|
||||
|
|
@ -403,14 +403,14 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
|||
for (krate, path, _default) in krates("std_shim") {
|
||||
rules.bench(&krate.bench_step, path)
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.dep(|s| s.name("emulator-copy-libs"))
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
Mode::Libstd, TestKind::Bench,
|
||||
Some(&krate.name)));
|
||||
}
|
||||
rules.bench("bench-std-all", "path/to/nowhere")
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.dep(|s| s.name("emulator-copy-libs"))
|
||||
.default(true)
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
Mode::Libstd, TestKind::Bench, None));
|
||||
|
|
@ -418,21 +418,21 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
|||
for (krate, path, _default) in krates("test_shim") {
|
||||
rules.test(&krate.test_step, path)
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.dep(|s| s.name("emulator-copy-libs"))
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
Mode::Libtest, TestKind::Test,
|
||||
Some(&krate.name)));
|
||||
}
|
||||
rules.test("check-test-all", "path/to/nowhere")
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.dep(|s| s.name("emulator-copy-libs"))
|
||||
.default(true)
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
Mode::Libtest, TestKind::Test, None));
|
||||
for (krate, path, _default) in krates("rustc-main") {
|
||||
rules.test(&krate.test_step, path)
|
||||
.dep(|s| s.name("librustc"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.dep(|s| s.name("emulator-copy-libs"))
|
||||
.host(true)
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
Mode::Librustc, TestKind::Test,
|
||||
|
|
@ -440,7 +440,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
|||
}
|
||||
rules.test("check-rustc-all", "path/to/nowhere")
|
||||
.dep(|s| s.name("librustc"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.dep(|s| s.name("emulator-copy-libs"))
|
||||
.default(true)
|
||||
.host(true)
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
|
|
@ -481,9 +481,34 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
|||
|
||||
rules.build("test-helpers", "src/rt/rust_test_helpers.c")
|
||||
.run(move |s| native::test_helpers(build, s.target));
|
||||
rules.test("android-copy-libs", "path/to/nowhere")
|
||||
|
||||
// Some test suites are run inside emulators, and most of our test binaries
|
||||
// are linked dynamically which means we need to ship the standard library
|
||||
// and such to the emulator ahead of time. This step represents this and is
|
||||
// a dependency of all test suites.
|
||||
//
|
||||
// Most of the time this step is a noop (the `check::emulator_copy_libs`
|
||||
// only does work if necessary). For some steps such as shipping data to
|
||||
// QEMU we have to build our own tools so we've got conditional dependencies
|
||||
// on those programs as well. Note that the QEMU client is built for the
|
||||
// build target (us) and the server is built for the target.
|
||||
rules.test("emulator-copy-libs", "path/to/nowhere")
|
||||
.dep(|s| s.name("libtest"))
|
||||
.run(move |s| check::android_copy_libs(build, &s.compiler(), s.target));
|
||||
.dep(move |s| {
|
||||
if build.qemu_rootfs(s.target).is_some() {
|
||||
s.name("tool-qemu-test-client").target(s.host).stage(0)
|
||||
} else {
|
||||
Step::noop()
|
||||
}
|
||||
})
|
||||
.dep(move |s| {
|
||||
if build.qemu_rootfs(s.target).is_some() {
|
||||
s.name("tool-qemu-test-server")
|
||||
} else {
|
||||
Step::noop()
|
||||
}
|
||||
})
|
||||
.run(move |s| check::emulator_copy_libs(build, &s.compiler(), s.target));
|
||||
|
||||
rules.test("check-bootstrap", "src/bootstrap")
|
||||
.default(true)
|
||||
|
|
@ -516,6 +541,12 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
|||
rules.build("tool-build-manifest", "src/tools/build-manifest")
|
||||
.dep(|s| s.name("libstd"))
|
||||
.run(move |s| compile::tool(build, s.stage, s.target, "build-manifest"));
|
||||
rules.build("tool-qemu-test-server", "src/tools/qemu-test-server")
|
||||
.dep(|s| s.name("libstd"))
|
||||
.run(move |s| compile::tool(build, s.stage, s.target, "qemu-test-server"));
|
||||
rules.build("tool-qemu-test-client", "src/tools/qemu-test-client")
|
||||
.dep(|s| s.name("libstd"))
|
||||
.run(move |s| compile::tool(build, s.stage, s.target, "qemu-test-client"));
|
||||
|
||||
// ========================================================================
|
||||
// Documentation targets
|
||||
|
|
|
|||
90
src/ci/docker/armhf-gnu/Dockerfile
Normal file
90
src/ci/docker/armhf-gnu/Dockerfile
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
FROM ubuntu:16.04
|
||||
|
||||
RUN apt-get update -y && apt-get install -y --no-install-recommends \
|
||||
bc \
|
||||
bzip2 \
|
||||
ca-certificates \
|
||||
cmake \
|
||||
cpio \
|
||||
curl \
|
||||
file \
|
||||
g++ \
|
||||
gcc-arm-linux-gnueabihf \
|
||||
git \
|
||||
libc6-dev \
|
||||
libc6-dev-armhf-cross \
|
||||
make \
|
||||
python2.7 \
|
||||
qemu-system-arm \
|
||||
xz-utils
|
||||
|
||||
ENV ARCH=arm \
|
||||
CROSS_COMPILE=arm-linux-gnueabihf-
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Compile the kernel that we're going to run and be emulating with. This is
|
||||
# basically just done to be compatible with the QEMU target that we're going
|
||||
# to be using when running tests. If any other kernel works or if any
|
||||
# other QEMU target works with some other stock kernel, we can use that too!
|
||||
#
|
||||
# The `vexpress_config` config file was a previously generated config file for
|
||||
# the kernel. This file was generated by running `make vexpress_defconfig`
|
||||
# followed by `make menuconfig` and then enabling the IPv6 protocol page.
|
||||
COPY vexpress_config /build/.config
|
||||
RUN curl https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.42.tar.xz | \
|
||||
tar xJf - && \
|
||||
cd /build/linux-4.4.42 && \
|
||||
cp /build/.config . && \
|
||||
make -j$(nproc) all && \
|
||||
cp arch/arm/boot/zImage /tmp && \
|
||||
cd /build && \
|
||||
rm -rf linux-4.4.42
|
||||
|
||||
# Compile an instance of busybox as this provides a lightweight system and init
|
||||
# binary which we will boot into. Only trick here is configuring busybox to
|
||||
# build static binaries.
|
||||
RUN curl https://www.busybox.net/downloads/busybox-1.21.1.tar.bz2 | tar xjf - && \
|
||||
cd busybox-1.21.1 && \
|
||||
make defconfig && \
|
||||
sed -i 's/.*CONFIG_STATIC.*/CONFIG_STATIC=y/' .config && \
|
||||
make -j$(nproc) && \
|
||||
make install && \
|
||||
mv _install /tmp/rootfs && \
|
||||
cd /build && \
|
||||
rm -rf busybox-1.12.1
|
||||
|
||||
# Download the ubuntu rootfs, which we'll use as a chroot for all our tests.
|
||||
WORKDIR /tmp
|
||||
RUN mkdir rootfs/ubuntu
|
||||
RUN curl http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/ubuntu-base-16.04-core-armhf.tar.gz | \
|
||||
tar xzf - -C rootfs/ubuntu && \
|
||||
cd rootfs && mkdir proc sys dev etc etc/init.d
|
||||
|
||||
# Copy over our init script, which starts up our test server and also a few
|
||||
# other misc tasks.
|
||||
COPY rcS rootfs/etc/init.d/rcS
|
||||
RUN chmod +x rootfs/etc/init.d/rcS
|
||||
|
||||
# Helper to quickly fill the entropy pool in the kernel.
|
||||
COPY addentropy.c /tmp/
|
||||
RUN arm-linux-gnueabihf-gcc addentropy.c -o rootfs/addentropy -static
|
||||
|
||||
# TODO: What is this?!
|
||||
RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/current/images/device-tree/vexpress-v2p-ca15-tc1.dtb
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--target=arm-unknown-linux-gnueabihf \
|
||||
--qemu-armhf-rootfs=/tmp/rootfs
|
||||
ENV SCRIPT python2.7 ../x.py test --target arm-unknown-linux-gnueabihf
|
||||
|
||||
ENV NO_CHANGE_USER=1
|
||||
43
src/ci/docker/armhf-gnu/addentropy.c
Normal file
43
src/ci/docker/armhf-gnu/addentropy.c
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2017 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.
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#define N 2048
|
||||
|
||||
struct entropy {
|
||||
int ent_count;
|
||||
int size;
|
||||
unsigned char data[N];
|
||||
};
|
||||
|
||||
int main() {
|
||||
struct entropy buf;
|
||||
ssize_t n;
|
||||
|
||||
int random_fd = open("/dev/random", O_RDWR);
|
||||
assert(random_fd >= 0);
|
||||
|
||||
while ((n = read(0, &buf.data, N)) > 0) {
|
||||
buf.ent_count = n * 8;
|
||||
buf.size = n;
|
||||
if (ioctl(random_fd, RNDADDENTROPY, &buf) != 0) {
|
||||
perror("failed to add entropy");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
28
src/ci/docker/armhf-gnu/rcS
Normal file
28
src/ci/docker/armhf-gnu/rcS
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#!/bin/sh
|
||||
mount -t proc none /proc
|
||||
mount -t sysfs none /sys
|
||||
/sbin/mdev -s
|
||||
|
||||
# fill up our entropy pool, if we don't do this then anything with a hash map
|
||||
# will likely block forever as the kernel is pretty unlikely to have enough
|
||||
# entropy.
|
||||
/addentropy < /addentropy
|
||||
cat /dev/urandom | head -n 2048 | /addentropy
|
||||
|
||||
# Set up IP that qemu expects. This confgures eth0 with the public IP that QEMU
|
||||
# will communicate to as well as the loopback 127.0.0.1 address.
|
||||
ifconfig eth0 10.0.2.15
|
||||
ifconfig lo up
|
||||
|
||||
# Configure DNS resolution of 'localhost' to work
|
||||
echo 'hosts: files dns' >> /ubuntu/etc/nsswitch.conf
|
||||
echo '127.0.0.1 localhost' >> /ubuntu/etc/hosts
|
||||
|
||||
# prepare the chroot
|
||||
mount -t proc proc /ubuntu/proc/
|
||||
mount --rbind /sys /ubuntu/sys/
|
||||
mount --rbind /dev /ubuntu/dev/
|
||||
|
||||
# Execute our `testd` inside the ubuntu chroot
|
||||
cp /testd /ubuntu/testd
|
||||
chroot /ubuntu /testd &
|
||||
2910
src/ci/docker/armhf-gnu/vexpress_config
Normal file
2910
src/ci/docker/armhf-gnu/vexpress_config
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -21,17 +21,7 @@ RUN yum upgrade -y && yum install -y \
|
|||
ENV PATH=/rustroot/bin:$PATH
|
||||
ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib
|
||||
WORKDIR /tmp
|
||||
|
||||
# binutils < 2.22 has a bug where the 32-bit executables it generates
|
||||
# immediately segfault in Rust, so we need to install our own binutils.
|
||||
#
|
||||
# See https://github.com/rust-lang/rust/issues/20440 for more info
|
||||
COPY shared.sh build-binutils.sh /tmp/
|
||||
RUN ./build-binutils.sh
|
||||
|
||||
# Need a newer version of gcc than centos has to compile LLVM nowadays
|
||||
COPY build-gcc.sh /tmp/
|
||||
RUN ./build-gcc.sh
|
||||
|
||||
# We need a build of openssl which supports SNI to download artifacts from
|
||||
# static.rust-lang.org. This'll be used to link into libcurl below (and used
|
||||
|
|
@ -49,6 +39,16 @@ RUN ./build-openssl.sh
|
|||
COPY build-curl.sh /tmp/
|
||||
RUN ./build-curl.sh
|
||||
|
||||
# binutils < 2.22 has a bug where the 32-bit executables it generates
|
||||
# immediately segfault in Rust, so we need to install our own binutils.
|
||||
#
|
||||
# See https://github.com/rust-lang/rust/issues/20440 for more info
|
||||
RUN ./build-binutils.sh
|
||||
|
||||
# Need a newer version of gcc than centos has to compile LLVM nowadays
|
||||
COPY build-gcc.sh /tmp/
|
||||
RUN ./build-gcc.sh
|
||||
|
||||
# CentOS 5.5 has Python 2.4 by default, but LLVM needs 2.7+
|
||||
COPY build-python.sh /tmp/
|
||||
RUN ./build-python.sh
|
||||
|
|
@ -63,6 +63,11 @@ RUN ./build-git.sh
|
|||
COPY build-cmake.sh /tmp/
|
||||
RUN ./build-cmake.sh
|
||||
|
||||
# for sanitizers, we need kernel headers files newer than the ones CentOS ships
|
||||
# with so we install newer ones here
|
||||
COPY build-headers.sh /tmp/
|
||||
RUN ./build-headers.sh
|
||||
|
||||
RUN curl -Lo /rustroot/dumb-init \
|
||||
https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 && \
|
||||
chmod +x /rustroot/dumb-init
|
||||
|
|
@ -76,5 +81,5 @@ RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST |
|
|||
ENV HOSTS=i686-unknown-linux-gnu
|
||||
ENV HOSTS=$HOSTS,x86_64-unknown-linux-gnu
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended --enable-sanitizers
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
25
src/ci/docker/dist-x86-linux/build-headers.sh
Executable file
25
src/ci/docker/dist-x86-linux/build-headers.sh
Executable file
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
# Copyright 2017 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.
|
||||
|
||||
set -ex
|
||||
source shared.sh
|
||||
|
||||
curl https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.2.84.tar.xz | unxz | tar x
|
||||
|
||||
cd linux-3.2.84
|
||||
hide_output make mrproper
|
||||
hide_output make INSTALL_HDR_PATH=dest headers_install
|
||||
|
||||
find dest/include \( -name .install -o -name ..install.cmd \) -delete
|
||||
yes | cp -fr dest/include/* /usr/include
|
||||
|
||||
cd ..
|
||||
rm -rf linux-3.2.84
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
FROM ubuntu:16.04
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
g++ \
|
||||
make \
|
||||
file \
|
||||
curl \
|
||||
ca-certificates \
|
||||
python2.7 \
|
||||
git \
|
||||
cmake \
|
||||
sudo \
|
||||
gdb \
|
||||
xz-utils
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-rustbuild
|
||||
ENV RUST_CHECK_TARGET check
|
||||
|
|
@ -22,5 +22,5 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
|
|||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
|
||||
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --enable-sanitizers
|
||||
ENV SCRIPT python2.7 ../x.py test && python2.7 ../x.py dist
|
||||
|
|
|
|||
|
|
@ -11,11 +11,13 @@
|
|||
|
||||
set -e
|
||||
|
||||
if [ "$LOCAL_USER_ID" != "" ]; then
|
||||
useradd --shell /bin/bash -u $LOCAL_USER_ID -o -c "" -m user
|
||||
export HOME=/home/user
|
||||
unset LOCAL_USER_ID
|
||||
exec su --preserve-environment -c "env PATH=$PATH \"$0\"" user
|
||||
if [ "$NO_CHANGE_USER" = "" ]; then
|
||||
if [ "$LOCAL_USER_ID" != "" ]; then
|
||||
useradd --shell /bin/bash -u $LOCAL_USER_ID -o -c "" -m user
|
||||
export HOME=/home/user
|
||||
unset LOCAL_USER_ID
|
||||
exec su --preserve-environment -c "env PATH=$PATH \"$0\"" user
|
||||
fi
|
||||
fi
|
||||
|
||||
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-sccache"
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit a8fc4c169fac43a5dc204d4fd56ddb1739f8c178
|
||||
Subproject commit d30da544a8afc5d78391dee270bdf40e74a215d3
|
||||
|
|
@ -108,7 +108,7 @@ fn skip_prefix<'a, 'b>(line: &'a str, prefix: &'b str) -> &'a str {
|
|||
|
||||
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
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -117,6 +117,30 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
Initialization of a data structure (struct, enum, union) can be simplified if
|
||||
fields of the data structure are initialized with variables which has same
|
||||
names as the fields.
|
||||
|
||||
```
|
||||
#![feature(field_init_shorthand)]
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Person<'a> {
|
||||
name: &'a str,
|
||||
age: u8
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Create struct with field init shorthand
|
||||
let name = "Peter";
|
||||
let age = 27;
|
||||
let peter = Person { name, age };
|
||||
|
||||
// Print debug struct
|
||||
println!("{:?}", peter);
|
||||
}
|
||||
```
|
||||
|
||||
# Update syntax
|
||||
|
||||
A `struct` can include `..` to indicate that you want to use a copy of some
|
||||
|
|
|
|||
|
|
@ -6,32 +6,44 @@ nav {
|
|||
}
|
||||
</style>
|
||||
|
||||
This is an index of the documentation included with the Rust
|
||||
compiler. For more comprehensive documentation see [the
|
||||
website](https://www.rust-lang.org).
|
||||
This page is an overview of the documentation included with your Rust install.
|
||||
Other unofficial documentation may exist elsewhere; for example, the [Rust
|
||||
Learning] project collects documentation from the community, and [Docs.rs]
|
||||
builds documentation for individual Rust packages.
|
||||
|
||||
[**The Rust Programming Language**][book]. Also known as "The Book",
|
||||
The Rust Programming Language is the most comprehensive resource for
|
||||
all topics related to Rust, and is the primary official document of
|
||||
the language.
|
||||
## API Documentation
|
||||
|
||||
[**The Rust Reference**][ref]. While Rust does not have a
|
||||
specification, the reference tries to describe its working in
|
||||
detail. It is accurate, but not necessarily complete.
|
||||
Rust provides a standard library with a number of features; [we host its
|
||||
documentation here][api].
|
||||
|
||||
[**Standard Library API Reference**][api]. Documentation for the
|
||||
standard library.
|
||||
## Reference Documentation
|
||||
|
||||
[**The Rustonomicon**][nomicon]. An entire book dedicated to
|
||||
explaining how to write unsafe Rust code. It is for advanced Rust
|
||||
programmers.
|
||||
Rust does not yet have a formal specification, but we have [a reference document
|
||||
][ref]. It is guaranteed to be accurate, but not complete. We now have a
|
||||
policy that all new features must be included in the reference before
|
||||
stabilization; however, we are still back-filling things that landed before
|
||||
then. That work is being tracked [here][38643].
|
||||
|
||||
[**Compiler Error Index**][err]. Extended explanations of
|
||||
the errors produced by the Rust compiler.
|
||||
## Extended Error Documentation
|
||||
|
||||
[book]: book/index.html
|
||||
[ref]: reference.html
|
||||
Many of Rust's errors come with error codes, and you can request extended
|
||||
diagnostics from the compiler on those errors. We also [have the text of those
|
||||
extended errors on the web][err], if you prefer to read them that way.
|
||||
|
||||
## The Rust Bookshelf
|
||||
|
||||
Rust provides a number of book-length sets of documentation, collectively
|
||||
nicknamed 'The Rust Bookshelf.'
|
||||
|
||||
* [The Rust Programming Language][book] teaches you how to program in Rust.
|
||||
* [The Rustonomicon][nomicon] is your guidebook to the dark arts of unsafe Rust.
|
||||
|
||||
[Rust Learning]: https://github.com/ctjhoa/rust-learning
|
||||
[Docs.rs]: https://docs.rs/
|
||||
[api]: std/index.html
|
||||
[nomicon]: nomicon/index.html
|
||||
[ref]: reference.html
|
||||
[38643]: https://github.com/rust-lang/rust/issues/38643
|
||||
[err]: error-index.html
|
||||
[book]: book/index.html
|
||||
[nomicon]: nomicon/index.html
|
||||
|
||||
|
|
|
|||
|
|
@ -1291,15 +1291,18 @@ guaranteed to refer to the same memory address.
|
|||
|
||||
Constant values must not have destructors, and otherwise permit most forms of
|
||||
data. Constants may refer to the address of other constants, in which case the
|
||||
address will have the `static` lifetime. The compiler is, however, still at
|
||||
liberty to translate the constant many times, so the address referred to may not
|
||||
be stable.
|
||||
address will have elided lifetimes where applicable, otherwise – in most cases –
|
||||
defaulting to the `static` lifetime. (See below on [static lifetime elision].)
|
||||
The compiler is, however, still at liberty to translate the constant many times,
|
||||
so the address referred to may not be stable.
|
||||
|
||||
[static lifetime elision]: #static-lifetime-elision
|
||||
|
||||
Constants must be explicitly typed. The type may be `bool`, `char`, a number, or
|
||||
a type derived from those primitive types. The derived types are references with
|
||||
the `static` lifetime, fixed-size arrays, tuples, enum variants, and structs.
|
||||
|
||||
```
|
||||
```rust
|
||||
const BIT1: u32 = 1 << 0;
|
||||
const BIT2: u32 = 1 << 1;
|
||||
|
||||
|
|
@ -1317,6 +1320,8 @@ const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings {
|
|||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Static items
|
||||
|
||||
A *static item* is similar to a *constant*, except that it represents a precise
|
||||
|
|
@ -1351,7 +1356,7 @@ running in the same process.
|
|||
Mutable statics are still very useful, however. They can be used with C
|
||||
libraries and can also be bound from C libraries (in an `extern` block).
|
||||
|
||||
```
|
||||
```rust
|
||||
# fn atomic_add(_: &mut u32, _: u32) -> u32 { 2 }
|
||||
|
||||
static mut LEVELS: u32 = 0;
|
||||
|
|
@ -1375,6 +1380,53 @@ unsafe fn bump_levels_unsafe2() -> u32 {
|
|||
Mutable statics have the same restrictions as normal statics, except that the
|
||||
type of the value is not required to ascribe to `Sync`.
|
||||
|
||||
#### `'static` lifetime elision
|
||||
|
||||
[Unstable] Both constant and static declarations of reference types have
|
||||
*implicit* `'static` lifetimes unless an explicit lifetime is specified. As
|
||||
such, the constant declarations involving `'static` above may be written
|
||||
without the lifetimes. Returning to our previous example:
|
||||
|
||||
```rust
|
||||
# #![feature(static_in_const)]
|
||||
const BIT1: u32 = 1 << 0;
|
||||
const BIT2: u32 = 1 << 1;
|
||||
|
||||
const BITS: [u32; 2] = [BIT1, BIT2];
|
||||
const STRING: &str = "bitstring";
|
||||
|
||||
struct BitsNStrings<'a> {
|
||||
mybits: [u32; 2],
|
||||
mystring: &'a str,
|
||||
}
|
||||
|
||||
const BITS_N_STRINGS: BitsNStrings = BitsNStrings {
|
||||
mybits: BITS,
|
||||
mystring: STRING,
|
||||
};
|
||||
```
|
||||
|
||||
Note that if the `static` or `const` items include function or closure
|
||||
references, which themselves include references, the compiler will first try the
|
||||
standard elision rules ([see discussion in the nomicon][elision-nomicon]). If it
|
||||
is unable to resolve the lifetimes by its usual rules, it will default to using
|
||||
the `'static` lifetime. By way of example:
|
||||
|
||||
[elision-nomicon]: https://doc.rust-lang.org/nomicon/lifetime-elision.html
|
||||
|
||||
```rust,ignore
|
||||
// Resolved as `fn<'a>(&'a str) -> &'a str`.
|
||||
const RESOLVED_SINGLE: fn(&str) -> &str = ..
|
||||
|
||||
// Resolved as `Fn<'a, 'b, 'c>(&'a Foo, &'b Bar, &'c Baz) -> usize`.
|
||||
const RESOLVED_MULTIPLE: Fn(&Foo, &Bar, &Baz) -> usize = ..
|
||||
|
||||
// There is insufficient information to bound the return reference lifetime
|
||||
// relative to the argument lifetimes, so the signature is resolved as
|
||||
// `Fn(&'static Foo, &'static Bar) -> &'static Baz`.
|
||||
const RESOLVED_STATIC: Fn(&Foo, &Bar) -> &Baz = ..
|
||||
```
|
||||
|
||||
### Traits
|
||||
|
||||
A _trait_ describes an abstract interface that types can
|
||||
|
|
@ -2072,7 +2124,9 @@ macro scope.
|
|||
|
||||
### Miscellaneous attributes
|
||||
|
||||
- `deprecated` - mark the item as deprecated; the full attribute is `#[deprecated(since = "crate version", note = "...")`, where both arguments are optional.
|
||||
- `deprecated` - mark the item as deprecated; the full attribute is
|
||||
`#[deprecated(since = "crate version", note = "...")`, where both arguments
|
||||
are optional.
|
||||
- `export_name` - on statics and functions, this determines the name of the
|
||||
exported symbol.
|
||||
- `link_section` - on statics and functions, this specifies the section of the
|
||||
|
|
@ -2114,10 +2168,15 @@ Sometimes one wants to have different compiler outputs from the same code,
|
|||
depending on build target, such as targeted operating system, or to enable
|
||||
release builds.
|
||||
|
||||
There are two kinds of configuration options, one that is either defined or not
|
||||
(`#[cfg(foo)]`), and the other that contains a string that can be checked
|
||||
against (`#[cfg(bar = "baz")]`). Currently, only compiler-defined configuration
|
||||
options can have the latter form.
|
||||
Configuration options are boolean (on or off) and are named either with a
|
||||
single identifier (e.g. `foo`) or an identifier and a string (e.g. `foo = "bar"`;
|
||||
the quotes are required and spaces around the `=` are unimportant). Note that
|
||||
similarly-named options, such as `foo`, `foo="bar"` and `foo="baz"` may each be set
|
||||
or unset independently.
|
||||
|
||||
Configuration options are either provided by the compiler or passed in on the
|
||||
command line using `--cfg` (e.g. `rustc main.rs --cfg foo --cfg 'bar="baz"'`).
|
||||
Rust code then checks for their presence using the `#[cfg(...)]` attribute:
|
||||
|
||||
```
|
||||
// The function is only included in the build when compiling for OSX
|
||||
|
|
@ -2196,7 +2255,10 @@ You can also set another attribute based on a `cfg` variable with `cfg_attr`:
|
|||
#[cfg_attr(a, b)]
|
||||
```
|
||||
|
||||
Will be the same as `#[b]` if `a` is set by `cfg`, and nothing otherwise.
|
||||
This is the same as `#[b]` if `a` is set by `cfg`, and nothing otherwise.
|
||||
|
||||
Lastly, configuration options can be used in expressions by invoking the `cfg!`
|
||||
macro: `cfg!(a)` evaluates to `true` if `a` is set, and `false` otherwise.
|
||||
|
||||
### Lint check attributes
|
||||
|
||||
|
|
@ -2481,9 +2543,6 @@ The currently implemented features of the reference compiler are:
|
|||
into a Rust program. This capability, especially the signature for the
|
||||
annotated function, is subject to change.
|
||||
|
||||
* `static_in_const` - Enables lifetime elision with a `'static` default for
|
||||
`const` and `static` item declarations.
|
||||
|
||||
* `thread_local` - The usage of the `#[thread_local]` attribute is experimental
|
||||
and should be seen as unstable. This attribute is used to
|
||||
declare a `static` as being unique per-thread leveraging
|
||||
|
|
@ -2757,6 +2816,28 @@ let base = Point3d {x: 1, y: 2, z: 3};
|
|||
Point3d {y: 0, z: 10, .. base};
|
||||
```
|
||||
|
||||
#### Struct field init shorthand
|
||||
|
||||
When initializing a data structure (struct, enum, union) with named fields,
|
||||
allow writing `fieldname` as a shorthand for `fieldname: fieldname`. This
|
||||
allows a compact syntax for initialization, with less duplication.
|
||||
|
||||
In the initializer for a `struct` with named fields, a `union` with named
|
||||
fields, or an enum variant with named fields, accept an identifier `field` as a
|
||||
shorthand for `field: field`.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
# #![feature(field_init_shorthand)]
|
||||
# struct Point3d { x: i32, y: i32, z: i32 }
|
||||
# let x = 0;
|
||||
# let y_value = 0;
|
||||
# let z = 0;
|
||||
Point3d { x: x, y: y_value, z: z };
|
||||
Point3d { x, y: y_value, z };
|
||||
```
|
||||
|
||||
### Block expressions
|
||||
|
||||
A _block expression_ is similar to a module in terms of the declarations that
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
FROM ubuntu:xenial
|
||||
|
||||
# curl
|
||||
# Download stage0, see src/bootstrap/bootstrap.py
|
||||
# g++
|
||||
# Compile LLVM binding in src/rustllvm
|
||||
# gdb
|
||||
# Used to run tests in src/test/debuginfo
|
||||
# git
|
||||
# Get commit hash and commit date in version string
|
||||
# make
|
||||
# Run build scripts in mk
|
||||
# libedit-dev zlib1g-dev
|
||||
# LLVM dependencies as packaged in Ubuntu
|
||||
# (They are optional, but Ubuntu package enables them)
|
||||
# llvm-3.7-dev (installed by llvm-3.7-tools)
|
||||
# LLVM
|
||||
# llvm-3.7-tools
|
||||
# FileCheck is used to run tests in src/test/codegen
|
||||
|
||||
RUN apt-get update && apt-get -y install \
|
||||
curl g++ gdb git make \
|
||||
libedit-dev zlib1g-dev \
|
||||
llvm-3.7-tools cmake
|
||||
|
||||
RUN mkdir /build
|
||||
WORKDIR /build
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
{
|
||||
osx-frameworks.rs-fails-otherwise-1
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite,possible
|
||||
fun:malloc
|
||||
...
|
||||
fun:__CFInitialize
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
osx-frameworks.rs-fails-otherwise-2
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:malloc_zone_calloc
|
||||
...
|
||||
fun:__CFInitialize
|
||||
fun:_ZN16ImageLoaderMachO11doImageInitERKN11ImageLoader11LinkContextE
|
||||
}
|
||||
|
||||
{
|
||||
osx-frameworks.rs-fails-otherwise-3
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:realloc
|
||||
...
|
||||
fun:_read_images
|
||||
fun:map_images_nolock
|
||||
...
|
||||
fun:_ZN4dyldL18notifyBatchPartialE17dyld_image_statesbPFPKcS0_jPK15dyld_image_infoE
|
||||
fun:_ZN4dyld36registerImageStateBatchChangeHandlerE17dyld_image_statesPFPKcS0_jPK15dyld_image_infoE
|
||||
fun:dyld_register_image_state_change_handler
|
||||
fun:_objc_init
|
||||
fun:_os_object_init
|
||||
}
|
||||
|
||||
{
|
||||
osx-frameworks.rs-fails-otherwise-4
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite,possible
|
||||
fun:calloc
|
||||
...
|
||||
fun:__CFInitialize
|
||||
fun:_ZN16ImageLoaderMachO11doImageInitERKN11ImageLoader11LinkContextE
|
||||
fun:_ZN16ImageLoaderMachO16doInitializationERKN11ImageLoader11LinkContextE
|
||||
fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE
|
||||
}
|
||||
|
||||
{
|
||||
osx-frameworks.rs-fails-otherwise-5
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite,possible
|
||||
fun:malloc_zone_malloc
|
||||
...
|
||||
fun:__CFInitialize
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
fails-since-xcode-7.2
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:malloc_zone_malloc
|
||||
fun:_objc_copyClassNamesForImage
|
||||
fun:_ZL9protocolsv
|
||||
fun:_Z9readClassP10objc_classbb
|
||||
fun:gc_init
|
||||
fun:_ZL33objc_initializeClassPair_internalP10objc_classPKcS0_S0_
|
||||
fun:layout_string_create
|
||||
fun:_ZL12realizeClassP10objc_class
|
||||
fun:_ZL22copySwiftV1MangledNamePKcb
|
||||
fun:_ZL22copySwiftV1MangledNamePKcb
|
||||
fun:_ZL22copySwiftV1MangledNamePKcb
|
||||
fun:_ZL22copySwiftV1MangledNamePKcb
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2012-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.
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import functools
|
||||
|
||||
STATUS = 0
|
||||
|
||||
def error_unless_permitted(env_var, message):
|
||||
global STATUS
|
||||
if not os.getenv(env_var):
|
||||
sys.stderr.write(message)
|
||||
STATUS = 1
|
||||
|
||||
def only_on(platforms):
|
||||
def decorator(func):
|
||||
@functools.wraps(func)
|
||||
def inner():
|
||||
if any(map(lambda x: sys.platform.startswith(x), platforms)):
|
||||
func()
|
||||
return inner
|
||||
return decorator
|
||||
|
||||
@only_on(['linux', 'darwin', 'freebsd', 'openbsd'])
|
||||
def check_rlimit_core():
|
||||
import resource
|
||||
soft, hard = resource.getrlimit(resource.RLIMIT_CORE)
|
||||
if soft > 0:
|
||||
error_unless_permitted('ALLOW_NONZERO_RLIMIT_CORE', """\
|
||||
RLIMIT_CORE is set to a nonzero value (%d). During debuginfo, the test suite
|
||||
will segfault many rustc's, creating many potentially large core files.
|
||||
set ALLOW_NONZERO_RLIMIT_CORE to ignore this warning
|
||||
""" % (soft))
|
||||
|
||||
@only_on(['win32'])
|
||||
def check_console_code_page():
|
||||
if '65001' not in subprocess.check_output(['cmd', '/c', 'chcp']):
|
||||
sys.stderr.write('Warning: the console output code page is not UTF-8, \
|
||||
some tests may fail. Use `cmd /c "chcp 65001"` to setup UTF-8 code page.\n')
|
||||
|
||||
def main():
|
||||
check_console_code_page()
|
||||
check_rlimit_core()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
sys.exit(STATUS)
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2012-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.
|
||||
|
||||
import glob
|
||||
import sys
|
||||
|
||||
if __name__ == '__main__':
|
||||
summaries = []
|
||||
|
||||
def summarise(fname):
|
||||
summary = {}
|
||||
with open(fname) as fd:
|
||||
for line in fd:
|
||||
splitline = line.strip().split(' ')
|
||||
if len(splitline) == 1:
|
||||
continue
|
||||
status = splitline[0]
|
||||
test = splitline[-1]
|
||||
# track bench runs
|
||||
if splitline[1] == 'ns/iter':
|
||||
status = 'bench'
|
||||
if status not in summary:
|
||||
summary[status] = []
|
||||
summary[status].append(test)
|
||||
summaries.append((fname, summary))
|
||||
|
||||
def count(t):
|
||||
return sum(map(lambda f: len(f[1].get(t, [])), summaries))
|
||||
|
||||
logfiles = sys.argv[1:]
|
||||
for files in map(glob.glob, logfiles):
|
||||
map(summarise, files)
|
||||
ok = count('ok')
|
||||
failed = count('failed')
|
||||
ignored = count('ignored')
|
||||
measured = count('bench')
|
||||
print("summary of %d test runs: %d passed; %d failed; %d ignored; %d measured" %
|
||||
(len(logfiles), ok, failed, ignored, measured))
|
||||
print("")
|
||||
|
||||
if failed > 0:
|
||||
print("failed tests:")
|
||||
for f, s in summaries:
|
||||
failures = s.get('failed', [])
|
||||
if len(failures) > 0:
|
||||
print(" %s:" % (f))
|
||||
for test in failures:
|
||||
print(" %s" % (test))
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# 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.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
path = os.path.abspath(os.path.join(os.path.dirname(__file__), "../bootstrap"))
|
||||
sys.path.append(path)
|
||||
|
||||
import bootstrap
|
||||
|
||||
def main(triple):
|
||||
src_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../.."))
|
||||
data = bootstrap.stage0_data(src_root)
|
||||
|
||||
channel, date = data['rustc'].split('-', 1)
|
||||
|
||||
dl_dir = 'dl'
|
||||
if not os.path.exists(dl_dir):
|
||||
os.makedirs(dl_dir)
|
||||
|
||||
filename = 'rustc-{}-{}.tar.gz'.format(channel, triple)
|
||||
url = 'https://static.rust-lang.org/dist/{}/{}'.format(date, filename)
|
||||
dst = dl_dir + '/' + filename
|
||||
bootstrap.get(url, dst)
|
||||
|
||||
stage0_dst = triple + '/stage0'
|
||||
if os.path.exists(stage0_dst):
|
||||
for root, _, files in os.walk(stage0_dst):
|
||||
for f in files:
|
||||
os.unlink(os.path.join(root, f))
|
||||
else:
|
||||
os.makedirs(stage0_dst)
|
||||
bootstrap.unpack(dst, stage0_dst, match='rustc', verbose=True)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1])
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
#!/bin/sh
|
||||
# Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
# file at the top-level directory of this distribution and at
|
||||
# http://rust-lang.org/COPYRIGHT.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
# option. This file may not be copied, modified, or distributed
|
||||
# except according to those terms.
|
||||
|
||||
TARG_DIR=$1
|
||||
PREFIX=$2
|
||||
RUSTLIBDIR=$3
|
||||
|
||||
LIB_DIR=lib
|
||||
LIB_PREFIX=lib
|
||||
|
||||
OS=`uname -s`
|
||||
case $OS in
|
||||
("Linux"|"FreeBSD"|"DragonFly"|"Bitrig"|"OpenBSD"|"SunOS"|"Haiku")
|
||||
BIN_SUF=
|
||||
LIB_SUF=.so
|
||||
;;
|
||||
("Darwin")
|
||||
BIN_SUF=
|
||||
LIB_SUF=.dylib
|
||||
;;
|
||||
(*)
|
||||
BIN_SUF=.exe
|
||||
LIB_SUF=.dll
|
||||
LIB_DIR=bin
|
||||
LIB_PREFIX=
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z $PREFIX ]; then
|
||||
echo "No local rust specified."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e ${PREFIX}/bin/rustc${BIN_SUF} ]; then
|
||||
echo "No local rust installed at ${PREFIX}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z $TARG_DIR ]; then
|
||||
echo "No target directory specified."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$TARG_DIR" in
|
||||
--print-rustc-release)
|
||||
# not actually copying to TARG_DIR, just print the local rustc version and exit
|
||||
${PREFIX}/bin/rustc${BIN_SUF} --version --verbose | sed -ne 's/^release: //p'
|
||||
;;
|
||||
*)
|
||||
|
||||
cp ${PREFIX}/bin/rustc${BIN_SUF} ${TARG_DIR}/stage0/bin/
|
||||
cp ${PREFIX}/${LIB_DIR}/${RUSTLIBDIR}/${TARG_DIR}/${LIB_DIR}/* ${TARG_DIR}/stage0/${LIB_DIR}/
|
||||
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}arena*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
||||
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}extra*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
||||
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}rust*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
||||
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}std*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
||||
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}syntax*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
||||
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}flate*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
||||
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}fmt_macros*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
||||
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}getopts*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
||||
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}graphviz*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
||||
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
|
||||
|
||||
esac
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
# Copyright 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.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
f = open(sys.argv[1], 'wb')
|
||||
|
||||
components = sys.argv[2].split() # splits on whitespace
|
||||
enable_static = sys.argv[3]
|
||||
llvm_config = sys.argv[4]
|
||||
stdcpp_name = sys.argv[5]
|
||||
use_libcpp = sys.argv[6]
|
||||
|
||||
f.write("""// Copyright 2013 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.
|
||||
|
||||
// WARNING: THIS IS A GENERATED FILE, DO NOT MODIFY
|
||||
// take a look at src/etc/mklldeps.py if you're interested
|
||||
""")
|
||||
|
||||
|
||||
def run(args):
|
||||
proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = proc.communicate()
|
||||
|
||||
if err:
|
||||
print("failed to run llvm_config: args = `{}`".format(args))
|
||||
print(err)
|
||||
sys.exit(1)
|
||||
return out
|
||||
|
||||
def runErr(args):
|
||||
proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = proc.communicate()
|
||||
|
||||
if err:
|
||||
return False, out
|
||||
else:
|
||||
return True, out
|
||||
|
||||
f.write("\n")
|
||||
|
||||
args = [llvm_config, '--shared-mode']
|
||||
args.extend(components)
|
||||
llvm_shared, out = runErr(args)
|
||||
if llvm_shared:
|
||||
llvm_shared = 'shared' in out
|
||||
|
||||
# LLVM libs
|
||||
args = [llvm_config, '--libs', '--system-libs']
|
||||
args.extend(components)
|
||||
out = run(args)
|
||||
for lib in out.strip().replace("\n", ' ').split(' '):
|
||||
if len(lib) == 0:
|
||||
continue
|
||||
# in some cases we get extra spaces in between libs so ignore those
|
||||
if len(lib) == 1 and lib == ' ':
|
||||
continue
|
||||
# not all libs strictly follow -lfoo, on Bitrig, there is -pthread
|
||||
if lib[0:2] == '-l':
|
||||
lib = lib.strip()[2:]
|
||||
elif lib[0] == '-':
|
||||
lib = lib.strip()[1:]
|
||||
# If this actually points at a literal file then we're on MSVC which now
|
||||
# prints full paths, so get just the name of the library and strip off the
|
||||
# trailing ".lib"
|
||||
elif os.path.exists(lib):
|
||||
lib = os.path.basename(lib)[:-4]
|
||||
elif lib[-4:] == '.lib':
|
||||
lib = lib[:-4]
|
||||
f.write("#[link(name = \"" + lib + "\"")
|
||||
if not llvm_shared and 'LLVM' in lib:
|
||||
f.write(", kind = \"static\"")
|
||||
f.write(")]\n")
|
||||
|
||||
# LLVM ldflags
|
||||
out = run([llvm_config, '--ldflags'])
|
||||
for lib in out.strip().split(' '):
|
||||
if lib[:2] == "-l":
|
||||
f.write("#[link(name = \"" + lib[2:] + "\")]\n")
|
||||
|
||||
# C++ runtime library
|
||||
out = run([llvm_config, '--cxxflags'])
|
||||
if enable_static == '1':
|
||||
assert('stdlib=libc++' not in out)
|
||||
f.write("#[link(name = \"" + stdcpp_name + "\", kind = \"static\")]\n")
|
||||
else:
|
||||
# Note that we use `cfg_attr` here because on MSVC the C++ standard library
|
||||
# is not c++ or stdc++, but rather the linker takes care of linking the
|
||||
# right standard library.
|
||||
if use_libcpp != "0" or 'stdlib=libc++' in out:
|
||||
f.write("#[cfg_attr(not(target_env = \"msvc\"), link(name = \"c++\"))]\n")
|
||||
else:
|
||||
f.write("#[cfg_attr(not(target_env = \"msvc\"), link(name = \"" + stdcpp_name + "\"))]\n")
|
||||
|
||||
# Attach everything to an extern block
|
||||
f.write("extern {}\n")
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
{
|
||||
goddammit-llvm-why-u-no-valgrind
|
||||
Memcheck:Cond
|
||||
fun:*
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
down-with-thread-dtors.rs-fails-otherwise-1
|
||||
Memcheck:Addr1
|
||||
...
|
||||
fun:tlv_finalize
|
||||
fun:_pthread_tsd_cleanup
|
||||
fun:_pthread_exit
|
||||
...
|
||||
fun:_pthread_start
|
||||
fun:thread_start
|
||||
}
|
||||
|
||||
{
|
||||
down-with-thread-dtors.rs-fails-otherwise-2
|
||||
Memcheck:Addr2
|
||||
...
|
||||
fun:tlv_finalize
|
||||
fun:_pthread_tsd_cleanup
|
||||
fun:_pthread_exit
|
||||
...
|
||||
fun:_pthread_start
|
||||
fun:thread_start
|
||||
}
|
||||
|
||||
{
|
||||
down-with-thread-dtors.rs-fails-otherwise-3
|
||||
Memcheck:Addr4
|
||||
...
|
||||
fun:tlv_finalize
|
||||
fun:_pthread_tsd_cleanup
|
||||
fun:_pthread_exit
|
||||
...
|
||||
fun:_pthread_start
|
||||
fun:thread_start
|
||||
}
|
||||
|
||||
{
|
||||
down-with-thread-dtors.rs-fails-otherwise-4
|
||||
Memcheck:Addr8
|
||||
...
|
||||
fun:tlv_finalize
|
||||
fun:_pthread_tsd_cleanup
|
||||
fun:_pthread_exit
|
||||
...
|
||||
fun:_pthread_start
|
||||
fun:thread_start
|
||||
}
|
||||
|
||||
{
|
||||
down-with-thread-dtors.rs-fails-otherwise-5
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:tlv_allocate_and_initialize_for_key
|
||||
fun:tlv_get_addr
|
||||
...
|
||||
fun:start
|
||||
}
|
||||
|
|
@ -21,7 +21,6 @@ use std::process::Command;
|
|||
use build_helper::{run, rerun_if_changed_anything_in_dir, up_to_date};
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rustc-cfg=cargobuild");
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
// FIXME: This is a hack to support building targets that don't
|
||||
|
|
|
|||
|
|
@ -30,22 +30,6 @@ pub use imp::*;
|
|||
mod imp {
|
||||
use libc::{c_int, c_void, 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" {}
|
||||
|
||||
// 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).
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ std_unicode = { path = "../libstd_unicode" }
|
|||
name = "collectionstest"
|
||||
path = "../libcollectionstest/lib.rs"
|
||||
|
||||
# FIXME: need to extract benchmarks to separate crate
|
||||
#[[bench]]
|
||||
#name = "collectionstest"
|
||||
#path = "../libcollectionstest/lib.rs"
|
||||
[[bench]]
|
||||
name = "collectionsbenches"
|
||||
path = "../libcollections/benches/lib.rs"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
|
|
@ -8,13 +8,17 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
use std::iter::Iterator;
|
||||
use std::vec::Vec;
|
||||
use std::collections::BTreeMap;
|
||||
use std::__rand::{Rng, thread_rng};
|
||||
use test::{Bencher, black_box};
|
||||
|
||||
macro_rules! map_insert_rand_bench {
|
||||
($name: ident, $n: expr, $map: ident) => (
|
||||
#[bench]
|
||||
pub fn $name(b: &mut ::test::Bencher) {
|
||||
use std::__rand::{thread_rng, Rng};
|
||||
use test::black_box;
|
||||
|
||||
pub fn $name(b: &mut Bencher) {
|
||||
let n: usize = $n;
|
||||
let mut map = $map::new();
|
||||
// setup
|
||||
|
|
@ -39,9 +43,7 @@ macro_rules! map_insert_rand_bench {
|
|||
macro_rules! map_insert_seq_bench {
|
||||
($name: ident, $n: expr, $map: ident) => (
|
||||
#[bench]
|
||||
pub fn $name(b: &mut ::test::Bencher) {
|
||||
use test::black_box;
|
||||
|
||||
pub fn $name(b: &mut Bencher) {
|
||||
let mut map = $map::new();
|
||||
let n: usize = $n;
|
||||
// setup
|
||||
|
|
@ -64,12 +66,7 @@ macro_rules! map_insert_seq_bench {
|
|||
macro_rules! map_find_rand_bench {
|
||||
($name: ident, $n: expr, $map: ident) => (
|
||||
#[bench]
|
||||
pub fn $name(b: &mut ::test::Bencher) {
|
||||
use std::iter::Iterator;
|
||||
use std::__rand::{thread_rng, Rng};
|
||||
use std::vec::Vec;
|
||||
use test::black_box;
|
||||
|
||||
pub fn $name(b: &mut Bencher) {
|
||||
let mut map = $map::new();
|
||||
let n: usize = $n;
|
||||
|
||||
|
|
@ -97,9 +94,7 @@ macro_rules! map_find_rand_bench {
|
|||
macro_rules! map_find_seq_bench {
|
||||
($name: ident, $n: expr, $map: ident) => (
|
||||
#[bench]
|
||||
pub fn $name(b: &mut ::test::Bencher) {
|
||||
use test::black_box;
|
||||
|
||||
pub fn $name(b: &mut Bencher) {
|
||||
let mut map = $map::new();
|
||||
let n: usize = $n;
|
||||
|
||||
|
|
@ -118,3 +113,45 @@ macro_rules! map_find_seq_bench {
|
|||
}
|
||||
)
|
||||
}
|
||||
|
||||
map_insert_rand_bench!{insert_rand_100, 100, BTreeMap}
|
||||
map_insert_rand_bench!{insert_rand_10_000, 10_000, BTreeMap}
|
||||
|
||||
map_insert_seq_bench!{insert_seq_100, 100, BTreeMap}
|
||||
map_insert_seq_bench!{insert_seq_10_000, 10_000, BTreeMap}
|
||||
|
||||
map_find_rand_bench!{find_rand_100, 100, BTreeMap}
|
||||
map_find_rand_bench!{find_rand_10_000, 10_000, BTreeMap}
|
||||
|
||||
map_find_seq_bench!{find_seq_100, 100, BTreeMap}
|
||||
map_find_seq_bench!{find_seq_10_000, 10_000, BTreeMap}
|
||||
|
||||
fn bench_iter(b: &mut Bencher, size: i32) {
|
||||
let mut map = BTreeMap::<i32, i32>::new();
|
||||
let mut rng = thread_rng();
|
||||
|
||||
for _ in 0..size {
|
||||
map.insert(rng.gen(), rng.gen());
|
||||
}
|
||||
|
||||
b.iter(|| {
|
||||
for entry in &map {
|
||||
black_box(entry);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn iter_20(b: &mut Bencher) {
|
||||
bench_iter(b, 20);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn iter_1000(b: &mut Bencher) {
|
||||
bench_iter(b, 1000);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn iter_100000(b: &mut Bencher) {
|
||||
bench_iter(b, 100000);
|
||||
}
|
||||
11
src/libcollections/benches/btree/mod.rs
Normal file
11
src/libcollections/benches/btree/mod.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2017 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.
|
||||
|
||||
mod map;
|
||||
24
src/libcollections/benches/lib.rs
Normal file
24
src/libcollections/benches/lib.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2017 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.
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
#![feature(rand)]
|
||||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
mod btree;
|
||||
mod linked_list;
|
||||
mod string;
|
||||
mod str;
|
||||
mod slice;
|
||||
mod vec;
|
||||
mod vec_deque;
|
||||
87
src/libcollections/benches/linked_list.rs
Normal file
87
src/libcollections/benches/linked_list.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
// Copyright 2017 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::collections::LinkedList;
|
||||
use test::Bencher;
|
||||
|
||||
#[bench]
|
||||
fn bench_collect_into(b: &mut Bencher) {
|
||||
let v = &[0; 64];
|
||||
b.iter(|| {
|
||||
let _: LinkedList<_> = v.iter().cloned().collect();
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_front(b: &mut Bencher) {
|
||||
let mut m: LinkedList<_> = LinkedList::new();
|
||||
b.iter(|| {
|
||||
m.push_front(0);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_back(b: &mut Bencher) {
|
||||
let mut m: LinkedList<_> = LinkedList::new();
|
||||
b.iter(|| {
|
||||
m.push_back(0);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_back_pop_back(b: &mut Bencher) {
|
||||
let mut m: LinkedList<_> = LinkedList::new();
|
||||
b.iter(|| {
|
||||
m.push_back(0);
|
||||
m.pop_back();
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_front_pop_front(b: &mut Bencher) {
|
||||
let mut m: LinkedList<_> = LinkedList::new();
|
||||
b.iter(|| {
|
||||
m.push_front(0);
|
||||
m.pop_front();
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_iter(b: &mut Bencher) {
|
||||
let v = &[0; 128];
|
||||
let m: LinkedList<_> = v.iter().cloned().collect();
|
||||
b.iter(|| {
|
||||
assert!(m.iter().count() == 128);
|
||||
})
|
||||
}
|
||||
#[bench]
|
||||
fn bench_iter_mut(b: &mut Bencher) {
|
||||
let v = &[0; 128];
|
||||
let mut m: LinkedList<_> = v.iter().cloned().collect();
|
||||
b.iter(|| {
|
||||
assert!(m.iter_mut().count() == 128);
|
||||
})
|
||||
}
|
||||
#[bench]
|
||||
fn bench_iter_rev(b: &mut Bencher) {
|
||||
let v = &[0; 128];
|
||||
let m: LinkedList<_> = v.iter().cloned().collect();
|
||||
b.iter(|| {
|
||||
assert!(m.iter().rev().count() == 128);
|
||||
})
|
||||
}
|
||||
#[bench]
|
||||
fn bench_iter_mut_rev(b: &mut Bencher) {
|
||||
let v = &[0; 128];
|
||||
let mut m: LinkedList<_> = v.iter().cloned().collect();
|
||||
b.iter(|| {
|
||||
assert!(m.iter_mut().rev().count() == 128);
|
||||
})
|
||||
}
|
||||
280
src/libcollections/benches/slice.rs
Normal file
280
src/libcollections/benches/slice.rs
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
// Copyright 2017 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::{mem, ptr};
|
||||
use std::__rand::{Rng, thread_rng};
|
||||
|
||||
use test::{Bencher, black_box};
|
||||
|
||||
#[bench]
|
||||
fn iterator(b: &mut Bencher) {
|
||||
// peculiar numbers to stop LLVM from optimising the summation
|
||||
// out.
|
||||
let v: Vec<_> = (0..100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect();
|
||||
|
||||
b.iter(|| {
|
||||
let mut sum = 0;
|
||||
for x in &v {
|
||||
sum += *x;
|
||||
}
|
||||
// sum == 11806, to stop dead code elimination.
|
||||
if sum == 0 {
|
||||
panic!()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn mut_iterator(b: &mut Bencher) {
|
||||
let mut v = vec![0; 100];
|
||||
|
||||
b.iter(|| {
|
||||
let mut i = 0;
|
||||
for x in &mut v {
|
||||
*x = i;
|
||||
i += 1;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn concat(b: &mut Bencher) {
|
||||
let xss: Vec<Vec<i32>> = (0..100).map(|i| (0..i).collect()).collect();
|
||||
b.iter(|| {
|
||||
xss.concat();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn join(b: &mut Bencher) {
|
||||
let xss: Vec<Vec<i32>> = (0..100).map(|i| (0..i).collect()).collect();
|
||||
b.iter(|| xss.join(&0));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn push(b: &mut Bencher) {
|
||||
let mut vec = Vec::<i32>::new();
|
||||
b.iter(|| {
|
||||
vec.push(0);
|
||||
black_box(&vec);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn starts_with_same_vector(b: &mut Bencher) {
|
||||
let vec: Vec<_> = (0..100).collect();
|
||||
b.iter(|| vec.starts_with(&vec))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn starts_with_single_element(b: &mut Bencher) {
|
||||
let vec: Vec<_> = vec![0];
|
||||
b.iter(|| vec.starts_with(&vec))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn starts_with_diff_one_element_at_end(b: &mut Bencher) {
|
||||
let vec: Vec<_> = (0..100).collect();
|
||||
let mut match_vec: Vec<_> = (0..99).collect();
|
||||
match_vec.push(0);
|
||||
b.iter(|| vec.starts_with(&match_vec))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn ends_with_same_vector(b: &mut Bencher) {
|
||||
let vec: Vec<_> = (0..100).collect();
|
||||
b.iter(|| vec.ends_with(&vec))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn ends_with_single_element(b: &mut Bencher) {
|
||||
let vec: Vec<_> = vec![0];
|
||||
b.iter(|| vec.ends_with(&vec))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) {
|
||||
let vec: Vec<_> = (0..100).collect();
|
||||
let mut match_vec: Vec<_> = (0..100).collect();
|
||||
match_vec[0] = 200;
|
||||
b.iter(|| vec.starts_with(&match_vec))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn contains_last_element(b: &mut Bencher) {
|
||||
let vec: Vec<_> = (0..100).collect();
|
||||
b.iter(|| vec.contains(&99))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn zero_1kb_from_elem(b: &mut Bencher) {
|
||||
b.iter(|| vec![0u8; 1024]);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn zero_1kb_set_memory(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let mut v = Vec::<u8>::with_capacity(1024);
|
||||
unsafe {
|
||||
let vp = v.as_mut_ptr();
|
||||
ptr::write_bytes(vp, 0, 1024);
|
||||
v.set_len(1024);
|
||||
}
|
||||
v
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn zero_1kb_loop_set(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let mut v = Vec::<u8>::with_capacity(1024);
|
||||
unsafe {
|
||||
v.set_len(1024);
|
||||
}
|
||||
for i in 0..1024 {
|
||||
v[i] = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn zero_1kb_mut_iter(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let mut v = Vec::<u8>::with_capacity(1024);
|
||||
unsafe {
|
||||
v.set_len(1024);
|
||||
}
|
||||
for x in &mut v {
|
||||
*x = 0;
|
||||
}
|
||||
v
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn random_inserts(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| {
|
||||
let mut v = vec![(0, 0); 30];
|
||||
for _ in 0..100 {
|
||||
let l = v.len();
|
||||
v.insert(rng.gen::<usize>() % (l + 1), (1, 1));
|
||||
}
|
||||
})
|
||||
}
|
||||
#[bench]
|
||||
fn random_removes(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| {
|
||||
let mut v = vec![(0, 0); 130];
|
||||
for _ in 0..100 {
|
||||
let l = v.len();
|
||||
v.remove(rng.gen::<usize>() % l);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn gen_ascending(len: usize) -> Vec<u64> {
|
||||
(0..len as u64).collect()
|
||||
}
|
||||
|
||||
fn gen_descending(len: usize) -> Vec<u64> {
|
||||
(0..len as u64).rev().collect()
|
||||
}
|
||||
|
||||
fn gen_random(len: usize) -> Vec<u64> {
|
||||
let mut rng = thread_rng();
|
||||
rng.gen_iter::<u64>().take(len).collect()
|
||||
}
|
||||
|
||||
fn gen_mostly_ascending(len: usize) -> Vec<u64> {
|
||||
let mut rng = thread_rng();
|
||||
let mut v = gen_ascending(len);
|
||||
for _ in (0usize..).take_while(|x| x * x <= len) {
|
||||
let x = rng.gen::<usize>() % len;
|
||||
let y = rng.gen::<usize>() % len;
|
||||
v.swap(x, y);
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
fn gen_mostly_descending(len: usize) -> Vec<u64> {
|
||||
let mut rng = thread_rng();
|
||||
let mut v = gen_descending(len);
|
||||
for _ in (0usize..).take_while(|x| x * x <= len) {
|
||||
let x = rng.gen::<usize>() % len;
|
||||
let y = rng.gen::<usize>() % len;
|
||||
v.swap(x, y);
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
fn gen_big_random(len: usize) -> Vec<[u64; 16]> {
|
||||
let mut rng = thread_rng();
|
||||
rng.gen_iter().map(|x| [x; 16]).take(len).collect()
|
||||
}
|
||||
|
||||
fn gen_big_ascending(len: usize) -> Vec<[u64; 16]> {
|
||||
(0..len as u64).map(|x| [x; 16]).take(len).collect()
|
||||
}
|
||||
|
||||
fn gen_big_descending(len: usize) -> Vec<[u64; 16]> {
|
||||
(0..len as u64).rev().map(|x| [x; 16]).take(len).collect()
|
||||
}
|
||||
|
||||
macro_rules! sort_bench {
|
||||
($name:ident, $gen:expr, $len:expr) => {
|
||||
#[bench]
|
||||
fn $name(b: &mut Bencher) {
|
||||
b.iter(|| $gen($len).sort());
|
||||
b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort_bench!(sort_small_random, gen_random, 10);
|
||||
sort_bench!(sort_small_ascending, gen_ascending, 10);
|
||||
sort_bench!(sort_small_descending, gen_descending, 10);
|
||||
|
||||
sort_bench!(sort_small_big_random, gen_big_random, 10);
|
||||
sort_bench!(sort_small_big_ascending, gen_big_ascending, 10);
|
||||
sort_bench!(sort_small_big_descending, gen_big_descending, 10);
|
||||
|
||||
sort_bench!(sort_medium_random, gen_random, 100);
|
||||
sort_bench!(sort_medium_ascending, gen_ascending, 100);
|
||||
sort_bench!(sort_medium_descending, gen_descending, 100);
|
||||
|
||||
sort_bench!(sort_large_random, gen_random, 10000);
|
||||
sort_bench!(sort_large_ascending, gen_ascending, 10000);
|
||||
sort_bench!(sort_large_descending, gen_descending, 10000);
|
||||
sort_bench!(sort_large_mostly_ascending, gen_mostly_ascending, 10000);
|
||||
sort_bench!(sort_large_mostly_descending, gen_mostly_descending, 10000);
|
||||
|
||||
sort_bench!(sort_large_big_random, gen_big_random, 10000);
|
||||
sort_bench!(sort_large_big_ascending, gen_big_ascending, 10000);
|
||||
sort_bench!(sort_large_big_descending, gen_big_descending, 10000);
|
||||
|
||||
#[bench]
|
||||
fn sort_large_random_expensive(b: &mut Bencher) {
|
||||
let len = 10000;
|
||||
b.iter(|| {
|
||||
let mut v = gen_random(len);
|
||||
let mut count = 0;
|
||||
v.sort_by(|a: &u64, b: &u64| {
|
||||
count += 1;
|
||||
if count % 1_000_000_000 == 0 {
|
||||
panic!("should not happen");
|
||||
}
|
||||
(*a as f64).cos().partial_cmp(&(*b as f64).cos()).unwrap()
|
||||
});
|
||||
black_box(count);
|
||||
});
|
||||
b.bytes = len as u64 * mem::size_of::<u64>() as u64;
|
||||
}
|
||||
298
src/libcollections/benches/str.rs
Normal file
298
src/libcollections/benches/str.rs
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
// Copyright 2017 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 test::{Bencher, black_box};
|
||||
|
||||
#[bench]
|
||||
fn char_iterator(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
|
||||
b.iter(|| s.chars().count());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn char_iterator_for(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
|
||||
b.iter(|| {
|
||||
for ch in s.chars() { black_box(ch); }
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn char_iterator_ascii(b: &mut Bencher) {
|
||||
let s = "Mary had a little lamb, Little lamb
|
||||
Mary had a little lamb, Little lamb
|
||||
Mary had a little lamb, Little lamb
|
||||
Mary had a little lamb, Little lamb
|
||||
Mary had a little lamb, Little lamb
|
||||
Mary had a little lamb, Little lamb";
|
||||
|
||||
b.iter(|| s.chars().count());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn char_iterator_rev(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
|
||||
b.iter(|| s.chars().rev().count());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn char_iterator_rev_for(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
|
||||
b.iter(|| {
|
||||
for ch in s.chars().rev() { black_box(ch); }
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn char_indicesator(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
let len = s.chars().count();
|
||||
|
||||
b.iter(|| assert_eq!(s.char_indices().count(), len));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn char_indicesator_rev(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
let len = s.chars().count();
|
||||
|
||||
b.iter(|| assert_eq!(s.char_indices().rev().count(), len));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn split_unicode_ascii(b: &mut Bencher) {
|
||||
let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam";
|
||||
|
||||
b.iter(|| assert_eq!(s.split('V').count(), 3));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn split_ascii(b: &mut Bencher) {
|
||||
let s = "Mary had a little lamb, Little lamb, little-lamb.";
|
||||
let len = s.split(' ').count();
|
||||
|
||||
b.iter(|| assert_eq!(s.split(' ').count(), len));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn split_extern_fn(b: &mut Bencher) {
|
||||
let s = "Mary had a little lamb, Little lamb, little-lamb.";
|
||||
let len = s.split(' ').count();
|
||||
fn pred(c: char) -> bool { c == ' ' }
|
||||
|
||||
b.iter(|| assert_eq!(s.split(pred).count(), len));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn split_closure(b: &mut Bencher) {
|
||||
let s = "Mary had a little lamb, Little lamb, little-lamb.";
|
||||
let len = s.split(' ').count();
|
||||
|
||||
b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn split_slice(b: &mut Bencher) {
|
||||
let s = "Mary had a little lamb, Little lamb, little-lamb.";
|
||||
let len = s.split(' ').count();
|
||||
|
||||
let c: &[char] = &[' '];
|
||||
b.iter(|| assert_eq!(s.split(c).count(), len));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_join(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
let sep = "→";
|
||||
let v = vec![s, s, s, s, s, s, s, s, s, s];
|
||||
b.iter(|| {
|
||||
assert_eq!(v.join(sep).len(), s.len() * 10 + sep.len() * 9);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_contains_short_short(b: &mut Bencher) {
|
||||
let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
|
||||
let needle = "sit";
|
||||
|
||||
b.iter(|| {
|
||||
assert!(haystack.contains(needle));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_contains_short_long(b: &mut Bencher) {
|
||||
let haystack = "\
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
|
||||
ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
|
||||
eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
|
||||
sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
|
||||
tempus vel, gravida nec quam.
|
||||
|
||||
In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \
|
||||
sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \
|
||||
diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \
|
||||
lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \
|
||||
eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \
|
||||
interdum. Curabitur ut nisi justo.
|
||||
|
||||
Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \
|
||||
mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \
|
||||
lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \
|
||||
est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \
|
||||
felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \
|
||||
ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \
|
||||
feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \
|
||||
Aliquam sit amet placerat lorem.
|
||||
|
||||
Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \
|
||||
mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \
|
||||
Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \
|
||||
lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \
|
||||
suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \
|
||||
cursus accumsan.
|
||||
|
||||
Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \
|
||||
feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
|
||||
vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
|
||||
leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
|
||||
malesuada sollicitudin quam eu fermentum.";
|
||||
let needle = "english";
|
||||
|
||||
b.iter(|| {
|
||||
assert!(!haystack.contains(needle));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_contains_bad_naive(b: &mut Bencher) {
|
||||
let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||
let needle = "aaaaaaaab";
|
||||
|
||||
b.iter(|| {
|
||||
assert!(!haystack.contains(needle));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_contains_equal(b: &mut Bencher) {
|
||||
let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
|
||||
let needle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
|
||||
|
||||
b.iter(|| {
|
||||
assert!(haystack.contains(needle));
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! make_test_inner {
|
||||
($s:ident, $code:expr, $name:ident, $str:expr) => {
|
||||
#[bench]
|
||||
fn $name(bencher: &mut Bencher) {
|
||||
let mut $s = $str;
|
||||
black_box(&mut $s);
|
||||
bencher.iter(|| $code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! make_test {
|
||||
($name:ident, $s:ident, $code:expr) => {
|
||||
mod $name {
|
||||
use test::Bencher;
|
||||
use test::black_box;
|
||||
|
||||
// Short strings: 65 bytes each
|
||||
make_test_inner!($s, $code, short_ascii,
|
||||
"Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!");
|
||||
make_test_inner!($s, $code, short_mixed,
|
||||
"ศไทย中华Việt Nam; Mary had a little lamb, Little lam!");
|
||||
make_test_inner!($s, $code, short_pile_of_poo,
|
||||
"💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!");
|
||||
make_test_inner!($s, $code, long_lorem_ipsum,"\
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
|
||||
ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
|
||||
eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
|
||||
sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
|
||||
tempus vel, gravida nec quam.
|
||||
|
||||
In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \
|
||||
sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \
|
||||
diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \
|
||||
lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \
|
||||
eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \
|
||||
interdum. Curabitur ut nisi justo.
|
||||
|
||||
Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \
|
||||
mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \
|
||||
lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \
|
||||
est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \
|
||||
felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \
|
||||
ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \
|
||||
feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \
|
||||
Aliquam sit amet placerat lorem.
|
||||
|
||||
Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \
|
||||
mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \
|
||||
Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \
|
||||
lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \
|
||||
suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \
|
||||
cursus accumsan.
|
||||
|
||||
Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \
|
||||
feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
|
||||
vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
|
||||
leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
|
||||
malesuada sollicitudin quam eu fermentum!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
make_test!(chars_count, s, s.chars().count());
|
||||
|
||||
make_test!(contains_bang_str, s, s.contains("!"));
|
||||
make_test!(contains_bang_char, s, s.contains('!'));
|
||||
|
||||
make_test!(match_indices_a_str, s, s.match_indices("a").count());
|
||||
|
||||
make_test!(split_a_str, s, s.split("a").count());
|
||||
|
||||
make_test!(trim_ascii_char, s, {
|
||||
use std::ascii::AsciiExt;
|
||||
s.trim_matches(|c: char| c.is_ascii())
|
||||
});
|
||||
make_test!(trim_left_ascii_char, s, {
|
||||
use std::ascii::AsciiExt;
|
||||
s.trim_left_matches(|c: char| c.is_ascii())
|
||||
});
|
||||
make_test!(trim_right_ascii_char, s, {
|
||||
use std::ascii::AsciiExt;
|
||||
s.trim_right_matches(|c: char| c.is_ascii())
|
||||
});
|
||||
|
||||
make_test!(find_underscore_char, s, s.find('_'));
|
||||
make_test!(rfind_underscore_char, s, s.rfind('_'));
|
||||
make_test!(find_underscore_str, s, s.find("_"));
|
||||
|
||||
make_test!(find_zzz_char, s, s.find('\u{1F4A4}'));
|
||||
make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}'));
|
||||
make_test!(find_zzz_str, s, s.find("\u{1F4A4}"));
|
||||
|
||||
make_test!(split_space_char, s, s.split(' ').count());
|
||||
make_test!(split_terminator_space_char, s, s.split_terminator(' ').count());
|
||||
|
||||
make_test!(splitn_space_char, s, s.splitn(10, ' ').count());
|
||||
make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count());
|
||||
|
||||
make_test!(split_space_str, s, s.split(" ").count());
|
||||
make_test!(split_ad_str, s, s.split("ad").count());
|
||||
134
src/libcollections/benches/string.rs
Normal file
134
src/libcollections/benches/string.rs
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
// Copyright 2017 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::iter::repeat;
|
||||
use test::Bencher;
|
||||
|
||||
#[bench]
|
||||
fn bench_with_capacity(b: &mut Bencher) {
|
||||
b.iter(|| String::with_capacity(100));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_str(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
b.iter(|| {
|
||||
let mut r = String::new();
|
||||
r.push_str(s);
|
||||
});
|
||||
}
|
||||
|
||||
const REPETITIONS: u64 = 10_000;
|
||||
|
||||
#[bench]
|
||||
fn bench_push_str_one_byte(b: &mut Bencher) {
|
||||
b.bytes = REPETITIONS;
|
||||
b.iter(|| {
|
||||
let mut r = String::new();
|
||||
for _ in 0..REPETITIONS {
|
||||
r.push_str("a")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_char_one_byte(b: &mut Bencher) {
|
||||
b.bytes = REPETITIONS;
|
||||
b.iter(|| {
|
||||
let mut r = String::new();
|
||||
for _ in 0..REPETITIONS {
|
||||
r.push('a')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_char_two_bytes(b: &mut Bencher) {
|
||||
b.bytes = REPETITIONS * 2;
|
||||
b.iter(|| {
|
||||
let mut r = String::new();
|
||||
for _ in 0..REPETITIONS {
|
||||
r.push('â')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn from_utf8_lossy_100_ascii(b: &mut Bencher) {
|
||||
let s = b"Hello there, the quick brown fox jumped over the lazy dog! \
|
||||
Lorem ipsum dolor sit amet, consectetur. ";
|
||||
|
||||
assert_eq!(100, s.len());
|
||||
b.iter(|| {
|
||||
let _ = String::from_utf8_lossy(s);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn from_utf8_lossy_100_multibyte(b: &mut Bencher) {
|
||||
let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes();
|
||||
assert_eq!(100, s.len());
|
||||
b.iter(|| {
|
||||
let _ = String::from_utf8_lossy(s);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn from_utf8_lossy_invalid(b: &mut Bencher) {
|
||||
let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
|
||||
b.iter(|| {
|
||||
let _ = String::from_utf8_lossy(s);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn from_utf8_lossy_100_invalid(b: &mut Bencher) {
|
||||
let s = repeat(0xf5).take(100).collect::<Vec<_>>();
|
||||
b.iter(|| {
|
||||
let _ = String::from_utf8_lossy(&s);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_exact_size_shrink_to_fit(b: &mut Bencher) {
|
||||
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
|
||||
Lorem ipsum dolor sit amet, consectetur. ";
|
||||
// ensure our operation produces an exact-size string before we benchmark it
|
||||
let mut r = String::with_capacity(s.len());
|
||||
r.push_str(s);
|
||||
assert_eq!(r.len(), r.capacity());
|
||||
b.iter(|| {
|
||||
let mut r = String::with_capacity(s.len());
|
||||
r.push_str(s);
|
||||
r.shrink_to_fit();
|
||||
r
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_str(b: &mut Bencher) {
|
||||
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
|
||||
Lorem ipsum dolor sit amet, consectetur. ";
|
||||
b.iter(|| String::from(s))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from(b: &mut Bencher) {
|
||||
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
|
||||
Lorem ipsum dolor sit amet, consectetur. ";
|
||||
b.iter(|| String::from(s))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_to_string(b: &mut Bencher) {
|
||||
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
|
||||
Lorem ipsum dolor sit amet, consectetur. ";
|
||||
b.iter(|| s.to_string())
|
||||
}
|
||||
492
src/libcollections/benches/vec.rs
Normal file
492
src/libcollections/benches/vec.rs
Normal file
|
|
@ -0,0 +1,492 @@
|
|||
// Copyright 2017 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 test::Bencher;
|
||||
use std::iter::{FromIterator, repeat};
|
||||
|
||||
#[bench]
|
||||
fn bench_new(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let v: Vec<u32> = Vec::new();
|
||||
assert_eq!(v.len(), 0);
|
||||
assert_eq!(v.capacity(), 0);
|
||||
})
|
||||
}
|
||||
|
||||
fn do_bench_with_capacity(b: &mut Bencher, src_len: usize) {
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let v: Vec<u32> = Vec::with_capacity(src_len);
|
||||
assert_eq!(v.len(), 0);
|
||||
assert_eq!(v.capacity(), src_len);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_with_capacity_0000(b: &mut Bencher) {
|
||||
do_bench_with_capacity(b, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_with_capacity_0010(b: &mut Bencher) {
|
||||
do_bench_with_capacity(b, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_with_capacity_0100(b: &mut Bencher) {
|
||||
do_bench_with_capacity(b, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_with_capacity_1000(b: &mut Bencher) {
|
||||
do_bench_with_capacity(b, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_from_fn(b: &mut Bencher, src_len: usize) {
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let dst = (0..src_len).collect::<Vec<_>>();
|
||||
assert_eq!(dst.len(), src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_fn_0000(b: &mut Bencher) {
|
||||
do_bench_from_fn(b, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_fn_0010(b: &mut Bencher) {
|
||||
do_bench_from_fn(b, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_fn_0100(b: &mut Bencher) {
|
||||
do_bench_from_fn(b, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_fn_1000(b: &mut Bencher) {
|
||||
do_bench_from_fn(b, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_from_elem(b: &mut Bencher, src_len: usize) {
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let dst: Vec<usize> = repeat(5).take(src_len).collect();
|
||||
assert_eq!(dst.len(), src_len);
|
||||
assert!(dst.iter().all(|x| *x == 5));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_elem_0000(b: &mut Bencher) {
|
||||
do_bench_from_elem(b, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_elem_0010(b: &mut Bencher) {
|
||||
do_bench_from_elem(b, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_elem_0100(b: &mut Bencher) {
|
||||
do_bench_from_elem(b, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_elem_1000(b: &mut Bencher) {
|
||||
do_bench_from_elem(b, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_from_slice(b: &mut Bencher, src_len: usize) {
|
||||
let src: Vec<_> = FromIterator::from_iter(0..src_len);
|
||||
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let dst = src.clone()[..].to_vec();
|
||||
assert_eq!(dst.len(), src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_slice_0000(b: &mut Bencher) {
|
||||
do_bench_from_slice(b, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_slice_0010(b: &mut Bencher) {
|
||||
do_bench_from_slice(b, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_slice_0100(b: &mut Bencher) {
|
||||
do_bench_from_slice(b, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_slice_1000(b: &mut Bencher) {
|
||||
do_bench_from_slice(b, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_from_iter(b: &mut Bencher, src_len: usize) {
|
||||
let src: Vec<_> = FromIterator::from_iter(0..src_len);
|
||||
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let dst: Vec<_> = FromIterator::from_iter(src.clone());
|
||||
assert_eq!(dst.len(), src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_iter_0000(b: &mut Bencher) {
|
||||
do_bench_from_iter(b, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_iter_0010(b: &mut Bencher) {
|
||||
do_bench_from_iter(b, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_iter_0100(b: &mut Bencher) {
|
||||
do_bench_from_iter(b, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_iter_1000(b: &mut Bencher) {
|
||||
do_bench_from_iter(b, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_extend(b: &mut Bencher, dst_len: usize, src_len: usize) {
|
||||
let dst: Vec<_> = FromIterator::from_iter(0..dst_len);
|
||||
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
|
||||
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let mut dst = dst.clone();
|
||||
dst.extend(src.clone());
|
||||
assert_eq!(dst.len(), dst_len + src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_extend_0000_0000(b: &mut Bencher) {
|
||||
do_bench_extend(b, 0, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_extend_0000_0010(b: &mut Bencher) {
|
||||
do_bench_extend(b, 0, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_extend_0000_0100(b: &mut Bencher) {
|
||||
do_bench_extend(b, 0, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_extend_0000_1000(b: &mut Bencher) {
|
||||
do_bench_extend(b, 0, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_extend_0010_0010(b: &mut Bencher) {
|
||||
do_bench_extend(b, 10, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_extend_0100_0100(b: &mut Bencher) {
|
||||
do_bench_extend(b, 100, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_extend_1000_1000(b: &mut Bencher) {
|
||||
do_bench_extend(b, 1000, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_push_all(b: &mut Bencher, dst_len: usize, src_len: usize) {
|
||||
let dst: Vec<_> = FromIterator::from_iter(0..dst_len);
|
||||
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
|
||||
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let mut dst = dst.clone();
|
||||
dst.extend_from_slice(&src);
|
||||
assert_eq!(dst.len(), dst_len + src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_0000_0000(b: &mut Bencher) {
|
||||
do_bench_push_all(b, 0, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_0000_0010(b: &mut Bencher) {
|
||||
do_bench_push_all(b, 0, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_0000_0100(b: &mut Bencher) {
|
||||
do_bench_push_all(b, 0, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_0000_1000(b: &mut Bencher) {
|
||||
do_bench_push_all(b, 0, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_0010_0010(b: &mut Bencher) {
|
||||
do_bench_push_all(b, 10, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_0100_0100(b: &mut Bencher) {
|
||||
do_bench_push_all(b, 100, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_1000_1000(b: &mut Bencher) {
|
||||
do_bench_push_all(b, 1000, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_push_all_move(b: &mut Bencher, dst_len: usize, src_len: usize) {
|
||||
let dst: Vec<_> = FromIterator::from_iter(0..dst_len);
|
||||
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
|
||||
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let mut dst = dst.clone();
|
||||
dst.extend(src.clone());
|
||||
assert_eq!(dst.len(), dst_len + src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_move_0000_0000(b: &mut Bencher) {
|
||||
do_bench_push_all_move(b, 0, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_move_0000_0010(b: &mut Bencher) {
|
||||
do_bench_push_all_move(b, 0, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_move_0000_0100(b: &mut Bencher) {
|
||||
do_bench_push_all_move(b, 0, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_move_0000_1000(b: &mut Bencher) {
|
||||
do_bench_push_all_move(b, 0, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_move_0010_0010(b: &mut Bencher) {
|
||||
do_bench_push_all_move(b, 10, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_move_0100_0100(b: &mut Bencher) {
|
||||
do_bench_push_all_move(b, 100, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_move_1000_1000(b: &mut Bencher) {
|
||||
do_bench_push_all_move(b, 1000, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_clone(b: &mut Bencher, src_len: usize) {
|
||||
let src: Vec<usize> = FromIterator::from_iter(0..src_len);
|
||||
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let dst = src.clone();
|
||||
assert_eq!(dst.len(), src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_0000(b: &mut Bencher) {
|
||||
do_bench_clone(b, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_0010(b: &mut Bencher) {
|
||||
do_bench_clone(b, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_0100(b: &mut Bencher) {
|
||||
do_bench_clone(b, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_1000(b: &mut Bencher) {
|
||||
do_bench_clone(b, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_clone_from(b: &mut Bencher, times: usize, dst_len: usize, src_len: usize) {
|
||||
let dst: Vec<_> = FromIterator::from_iter(0..src_len);
|
||||
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
|
||||
|
||||
b.bytes = (times * src_len) as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let mut dst = dst.clone();
|
||||
|
||||
for _ in 0..times {
|
||||
dst.clone_from(&src);
|
||||
|
||||
assert_eq!(dst.len(), src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| dst_len + i == *x));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0000_0000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 0, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0000_0010(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 0, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0000_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 0, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0000_1000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 0, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0010_0010(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 10, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0100_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 100, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_1000_1000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 1000, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0010_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 10, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0100_1000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 100, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0010_0000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 10, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0100_0010(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 100, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_1000_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 1000, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0000_0000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 0, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0000_0010(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 0, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0000_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 0, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0000_1000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 0, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0010_0010(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 10, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0100_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 100, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_1000_1000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 1000, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0010_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 10, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0100_1000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 100, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0010_0000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 10, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0100_0010(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 100, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_1000_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 1000, 100)
|
||||
}
|
||||
57
src/libcollections/benches/vec_deque.rs
Normal file
57
src/libcollections/benches/vec_deque.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2017 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::collections::VecDeque;
|
||||
use test::{Bencher, black_box};
|
||||
|
||||
#[bench]
|
||||
fn bench_new(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let ring: VecDeque<i32> = VecDeque::new();
|
||||
black_box(ring);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_grow_1025(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let mut deq = VecDeque::new();
|
||||
for i in 0..1025 {
|
||||
deq.push_front(i);
|
||||
}
|
||||
black_box(deq);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_iter_1000(b: &mut Bencher) {
|
||||
let ring: VecDeque<_> = (0..1000).collect();
|
||||
|
||||
b.iter(|| {
|
||||
let mut sum = 0;
|
||||
for &i in &ring {
|
||||
sum += i;
|
||||
}
|
||||
black_box(sum);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_mut_iter_1000(b: &mut Bencher) {
|
||||
let mut ring: VecDeque<_> = (0..1000).collect();
|
||||
|
||||
b.iter(|| {
|
||||
let mut sum = 0;
|
||||
for i in &mut ring {
|
||||
sum += *i;
|
||||
}
|
||||
black_box(sum);
|
||||
})
|
||||
}
|
||||
|
|
@ -228,6 +228,15 @@ pub struct PeekMut<'a, T: 'a + Ord> {
|
|||
sift: bool,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, T: Ord + fmt::Debug> fmt::Debug for PeekMut<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("PeekMut")
|
||||
.field(&self.heap.data[0])
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
|
||||
impl<'a, T: Ord> Drop for PeekMut<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
|
|
@ -968,6 +977,15 @@ pub struct Iter<'a, T: 'a> {
|
|||
iter: slice::Iter<'a, T>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for Iter<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("Iter")
|
||||
.field(&self.iter.as_slice())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> Clone for Iter<'a, T> {
|
||||
|
|
@ -1016,6 +1034,15 @@ pub struct IntoIter<T> {
|
|||
iter: vec::IntoIter<T>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("IntoIter")
|
||||
.field(&self.iter.as_slice())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Iterator for IntoIter<T> {
|
||||
type Item = T;
|
||||
|
|
@ -1051,6 +1078,7 @@ impl<T> FusedIterator for IntoIter<T> {}
|
|||
|
||||
/// An iterator that drains a `BinaryHeap`.
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct Drain<'a, T: 'a> {
|
||||
iter: vec::Drain<'a, T>,
|
||||
}
|
||||
|
|
@ -1200,6 +1228,17 @@ where T: Clone + Ord {
|
|||
place: vec::PlaceBack<'a, T>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T: Clone + Ord + fmt::Debug> fmt::Debug for BinaryHeapPlace<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("BinaryHeapPlace")
|
||||
.field(&self.place)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
|
|
|
|||
|
|
@ -270,8 +270,16 @@ pub struct Iter<'a, K: 'a, V: 'a> {
|
|||
length: usize,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for Iter<'a, K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list().entries(self.clone()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A mutable iterator over a BTreeMap's entries.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct IterMut<'a, K: 'a, V: 'a> {
|
||||
range: RangeMut<'a, K, V>,
|
||||
length: usize,
|
||||
|
|
@ -285,20 +293,46 @@ pub struct IntoIter<K, V> {
|
|||
length: usize,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IntoIter<K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let range = Range {
|
||||
front: self.front.reborrow(),
|
||||
back: self.back.reborrow(),
|
||||
};
|
||||
f.debug_list().entries(range).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over a BTreeMap's keys.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Keys<'a, K: 'a, V: 'a> {
|
||||
inner: Iter<'a, K, V>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for Keys<'a, K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list().entries(self.inner.clone()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over a BTreeMap's values.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Values<'a, K: 'a, V: 'a> {
|
||||
inner: Iter<'a, K, V>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for Values<'a, K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list().entries(self.inner.clone()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A mutable iterator over a BTreeMap's values.
|
||||
#[stable(feature = "map_values_mut", since = "1.10.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct ValuesMut<'a, K: 'a, V: 'a> {
|
||||
inner: IterMut<'a, K, V>,
|
||||
}
|
||||
|
|
@ -309,6 +343,13 @@ pub struct Range<'a, K: 'a, V: 'a> {
|
|||
back: Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for Range<'a, K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list().entries(self.clone()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A mutable iterator over a sub-range of BTreeMap's entries.
|
||||
pub struct RangeMut<'a, K: 'a, V: 'a> {
|
||||
front: Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>,
|
||||
|
|
@ -318,6 +359,17 @@ pub struct RangeMut<'a, K: 'a, V: 'a> {
|
|||
_marker: PhantomData<&'a mut (K, V)>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for RangeMut<'a, K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let range = Range {
|
||||
front: self.front.reborrow(),
|
||||
back: self.back.reborrow(),
|
||||
};
|
||||
f.debug_list().entries(range).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A view into a single entry in a map, which may either be vacant or occupied.
|
||||
/// This enum is constructed from the [`entry`] method on [`BTreeMap`].
|
||||
///
|
||||
|
|
|
|||
|
|
@ -85,6 +85,15 @@ pub struct Iter<'a, T: 'a> {
|
|||
iter: Keys<'a, T, ()>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for Iter<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("Iter")
|
||||
.field(&self.iter.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// An owning iterator over a `BTreeSet`'s items.
|
||||
///
|
||||
/// This structure is created by the `into_iter` method on [`BTreeSet`]
|
||||
|
|
@ -92,6 +101,7 @@ pub struct Iter<'a, T: 'a> {
|
|||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct IntoIter<T> {
|
||||
iter: ::btree_map::IntoIter<T, ()>,
|
||||
}
|
||||
|
|
@ -102,6 +112,7 @@ pub struct IntoIter<T> {
|
|||
///
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`range`]: struct.BTreeSet.html#method.range
|
||||
#[derive(Debug)]
|
||||
pub struct Range<'a, T: 'a> {
|
||||
iter: ::btree_map::Range<'a, T, ()>,
|
||||
}
|
||||
|
|
@ -118,6 +129,15 @@ pub struct Difference<'a, T: 'a> {
|
|||
b: Peekable<Iter<'a, T>>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for Difference<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("Difference")
|
||||
.field(&self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A lazy iterator producing elements in the set symmetric difference (in-order).
|
||||
///
|
||||
/// This structure is created by the [`symmetric_difference`] method on
|
||||
|
|
@ -131,6 +151,15 @@ pub struct SymmetricDifference<'a, T: 'a> {
|
|||
b: Peekable<Iter<'a, T>>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for SymmetricDifference<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("SymmetricDifference")
|
||||
.field(&self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A lazy iterator producing elements in the set intersection (in-order).
|
||||
///
|
||||
/// This structure is created by the [`intersection`] method on [`BTreeSet`].
|
||||
|
|
@ -143,6 +172,15 @@ pub struct Intersection<'a, T: 'a> {
|
|||
b: Peekable<Iter<'a, T>>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for Intersection<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("Intersection")
|
||||
.field(&self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A lazy iterator producing elements in the set union (in-order).
|
||||
///
|
||||
/// This structure is created by the [`union`] method on [`BTreeSet`].
|
||||
|
|
@ -155,6 +193,15 @@ pub struct Union<'a, T: 'a> {
|
|||
b: Peekable<Iter<'a, T>>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for Union<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("Union")
|
||||
.field(&self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> BTreeSet<T> {
|
||||
/// Makes a new `BTreeSet` with a reasonable choice of B.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -222,6 +222,14 @@ pub struct Iter<E> {
|
|||
marker: marker::PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E: fmt::Debug> fmt::Debug for Iter<E> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("Iter")
|
||||
.field(&self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
|
||||
impl<E> Clone for Iter<E> {
|
||||
fn clone(&self) -> Iter<E> {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#![cfg_attr(test, allow(deprecated))] // rand
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_debug_implementations)]
|
||||
|
||||
#![feature(alloc)]
|
||||
#![feature(allow_internal_unstable)]
|
||||
|
|
|
|||
|
|
@ -65,6 +65,15 @@ pub struct Iter<'a, T: 'a> {
|
|||
marker: PhantomData<&'a Node<T>>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for Iter<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("Iter")
|
||||
.field(&self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME #19839: deriving is too aggressive on the bounds (T doesn't need to be Clone).
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> Clone for Iter<'a, T> {
|
||||
|
|
@ -82,6 +91,15 @@ pub struct IterMut<'a, T: 'a> {
|
|||
len: usize,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for IterMut<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("IterMut")
|
||||
.field(self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the elements of a `LinkedList`.
|
||||
#[derive(Clone)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -89,6 +107,15 @@ pub struct IntoIter<T> {
|
|||
list: LinkedList<T>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("IntoIter")
|
||||
.field(self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Node<T> {
|
||||
fn new(element: T) -> Self {
|
||||
Node {
|
||||
|
|
@ -1077,6 +1104,17 @@ pub struct FrontPlace<'a, T: 'a> {
|
|||
node: IntermediateBox<Node<T>>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "struct name and placement protocol are subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for FrontPlace<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("FrontPlace")
|
||||
.field(self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
|
|
@ -1121,6 +1159,17 @@ pub struct BackPlace<'a, T: 'a> {
|
|||
node: IntermediateBox<Node<T>>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "struct name and placement protocol are subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for BackPlace<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("BackPlace")
|
||||
.field(self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
// It's cleaner to just turn off the unused_imports warning than to fix them.
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use core::fmt;
|
||||
use core::str as core_str;
|
||||
use core::str::pattern::Pattern;
|
||||
use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
|
||||
|
|
@ -122,6 +123,13 @@ pub struct EncodeUtf16<'a> {
|
|||
encoder: Utf16Encoder<Chars<'a>>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a> fmt::Debug for EncodeUtf16<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("EncodeUtf16 { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "encode_utf16", since = "1.8.0")]
|
||||
impl<'a> Iterator for EncodeUtf16<'a> {
|
||||
type Item = u16;
|
||||
|
|
|
|||
|
|
@ -1990,6 +1990,13 @@ pub struct Drain<'a> {
|
|||
iter: Chars<'a>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a> fmt::Debug for Drain<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("Drain { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
unsafe impl<'a> Sync for Drain<'a> {}
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
|
|
|
|||
|
|
@ -2089,6 +2089,15 @@ pub struct Drain<'a, T: 'a> {
|
|||
vec: Shared<Vec<T>>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for Drain<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("Drain")
|
||||
.field(&self.iter.as_slice())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {}
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
|
|
@ -2155,6 +2164,7 @@ impl<'a, T> FusedIterator for Drain<'a, T> {}
|
|||
#[unstable(feature = "collection_placement",
|
||||
reason = "struct name and placement protocol are subject to change",
|
||||
issue = "30172")]
|
||||
#[derive(Debug)]
|
||||
pub struct PlaceBack<'a, T: 'a> {
|
||||
vec: &'a mut Vec<T>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1856,6 +1856,15 @@ pub struct Iter<'a, T: 'a> {
|
|||
head: usize,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for Iter<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("Iter")
|
||||
.field(&self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> Clone for Iter<'a, T> {
|
||||
|
|
@ -1928,6 +1937,15 @@ pub struct IterMut<'a, T: 'a> {
|
|||
head: usize,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for IterMut<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("IterMut")
|
||||
.field(&self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> Iterator for IterMut<'a, T> {
|
||||
type Item = &'a mut T;
|
||||
|
|
@ -1994,6 +2012,15 @@ pub struct IntoIter<T> {
|
|||
inner: VecDeque<T>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("IntoIter")
|
||||
.field(&self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Iterator for IntoIter<T> {
|
||||
type Item = T;
|
||||
|
|
@ -2037,6 +2064,15 @@ pub struct Drain<'a, T: 'a> {
|
|||
deque: Shared<VecDeque<T>>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for Drain<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("Drain")
|
||||
.field(&self.clone())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {}
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
|
|
|
|||
|
|
@ -606,52 +606,3 @@ fn test_split_off_large_random_sorted() {
|
|||
assert!(map.into_iter().eq(data.clone().into_iter().filter(|x| x.0 < key)));
|
||||
assert!(right.into_iter().eq(data.into_iter().filter(|x| x.0 >= key)));
|
||||
}
|
||||
|
||||
mod bench {
|
||||
use std::collections::BTreeMap;
|
||||
use std::__rand::{Rng, thread_rng};
|
||||
|
||||
use test::{Bencher, black_box};
|
||||
|
||||
map_insert_rand_bench!{insert_rand_100, 100, BTreeMap}
|
||||
map_insert_rand_bench!{insert_rand_10_000, 10_000, BTreeMap}
|
||||
|
||||
map_insert_seq_bench!{insert_seq_100, 100, BTreeMap}
|
||||
map_insert_seq_bench!{insert_seq_10_000, 10_000, BTreeMap}
|
||||
|
||||
map_find_rand_bench!{find_rand_100, 100, BTreeMap}
|
||||
map_find_rand_bench!{find_rand_10_000, 10_000, BTreeMap}
|
||||
|
||||
map_find_seq_bench!{find_seq_100, 100, BTreeMap}
|
||||
map_find_seq_bench!{find_seq_10_000, 10_000, BTreeMap}
|
||||
|
||||
fn bench_iter(b: &mut Bencher, size: i32) {
|
||||
let mut map = BTreeMap::<i32, i32>::new();
|
||||
let mut rng = thread_rng();
|
||||
|
||||
for _ in 0..size {
|
||||
map.insert(rng.gen(), rng.gen());
|
||||
}
|
||||
|
||||
b.iter(|| {
|
||||
for entry in &map {
|
||||
black_box(entry);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn iter_20(b: &mut Bencher) {
|
||||
bench_iter(b, 20);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn iter_1000(b: &mut Bencher) {
|
||||
bench_iter(b, 1000);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn iter_100000(b: &mut Bencher) {
|
||||
bench_iter(b, 100000);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,10 +35,6 @@ extern crate std_unicode;
|
|||
use std::hash::{Hash, Hasher};
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
mod bench;
|
||||
|
||||
mod binary_heap;
|
||||
mod btree;
|
||||
mod cow_str;
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@
|
|||
|
||||
use std::collections::LinkedList;
|
||||
|
||||
use test;
|
||||
|
||||
#[test]
|
||||
fn test_basic() {
|
||||
let mut m = LinkedList::<Box<_>>::new();
|
||||
|
|
@ -356,81 +354,6 @@ fn test_extend() {
|
|||
assert!(a.iter().eq(&[1, 2, 3, 4, 5, 6, 7]));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_collect_into(b: &mut test::Bencher) {
|
||||
let v = &[0; 64];
|
||||
b.iter(|| {
|
||||
let _: LinkedList<_> = v.iter().cloned().collect();
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_front(b: &mut test::Bencher) {
|
||||
let mut m: LinkedList<_> = LinkedList::new();
|
||||
b.iter(|| {
|
||||
m.push_front(0);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_back(b: &mut test::Bencher) {
|
||||
let mut m: LinkedList<_> = LinkedList::new();
|
||||
b.iter(|| {
|
||||
m.push_back(0);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_back_pop_back(b: &mut test::Bencher) {
|
||||
let mut m: LinkedList<_> = LinkedList::new();
|
||||
b.iter(|| {
|
||||
m.push_back(0);
|
||||
m.pop_back();
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_front_pop_front(b: &mut test::Bencher) {
|
||||
let mut m: LinkedList<_> = LinkedList::new();
|
||||
b.iter(|| {
|
||||
m.push_front(0);
|
||||
m.pop_front();
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_iter(b: &mut test::Bencher) {
|
||||
let v = &[0; 128];
|
||||
let m: LinkedList<_> = v.iter().cloned().collect();
|
||||
b.iter(|| {
|
||||
assert!(m.iter().count() == 128);
|
||||
})
|
||||
}
|
||||
#[bench]
|
||||
fn bench_iter_mut(b: &mut test::Bencher) {
|
||||
let v = &[0; 128];
|
||||
let mut m: LinkedList<_> = v.iter().cloned().collect();
|
||||
b.iter(|| {
|
||||
assert!(m.iter_mut().count() == 128);
|
||||
})
|
||||
}
|
||||
#[bench]
|
||||
fn bench_iter_rev(b: &mut test::Bencher) {
|
||||
let v = &[0; 128];
|
||||
let m: LinkedList<_> = v.iter().cloned().collect();
|
||||
b.iter(|| {
|
||||
assert!(m.iter().rev().count() == 128);
|
||||
})
|
||||
}
|
||||
#[bench]
|
||||
fn bench_iter_mut_rev(b: &mut test::Bencher) {
|
||||
let v = &[0; 128];
|
||||
let mut m: LinkedList<_> = v.iter().cloned().collect();
|
||||
b.iter(|| {
|
||||
assert!(m.iter_mut().rev().count() == 128);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contains() {
|
||||
let mut l = LinkedList::new();
|
||||
|
|
|
|||
|
|
@ -1170,276 +1170,3 @@ fn test_copy_from_slice_dst_shorter() {
|
|||
let mut dst = [0; 3];
|
||||
dst.copy_from_slice(&src);
|
||||
}
|
||||
|
||||
mod bench {
|
||||
use std::{mem, ptr};
|
||||
use std::__rand::{Rng, thread_rng};
|
||||
|
||||
use test::{Bencher, black_box};
|
||||
|
||||
#[bench]
|
||||
fn iterator(b: &mut Bencher) {
|
||||
// peculiar numbers to stop LLVM from optimising the summation
|
||||
// out.
|
||||
let v: Vec<_> = (0..100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect();
|
||||
|
||||
b.iter(|| {
|
||||
let mut sum = 0;
|
||||
for x in &v {
|
||||
sum += *x;
|
||||
}
|
||||
// sum == 11806, to stop dead code elimination.
|
||||
if sum == 0 {
|
||||
panic!()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn mut_iterator(b: &mut Bencher) {
|
||||
let mut v = vec![0; 100];
|
||||
|
||||
b.iter(|| {
|
||||
let mut i = 0;
|
||||
for x in &mut v {
|
||||
*x = i;
|
||||
i += 1;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn concat(b: &mut Bencher) {
|
||||
let xss: Vec<Vec<i32>> = (0..100).map(|i| (0..i).collect()).collect();
|
||||
b.iter(|| {
|
||||
xss.concat();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn join(b: &mut Bencher) {
|
||||
let xss: Vec<Vec<i32>> = (0..100).map(|i| (0..i).collect()).collect();
|
||||
b.iter(|| xss.join(&0));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn push(b: &mut Bencher) {
|
||||
let mut vec = Vec::<i32>::new();
|
||||
b.iter(|| {
|
||||
vec.push(0);
|
||||
black_box(&vec);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn starts_with_same_vector(b: &mut Bencher) {
|
||||
let vec: Vec<_> = (0..100).collect();
|
||||
b.iter(|| vec.starts_with(&vec))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn starts_with_single_element(b: &mut Bencher) {
|
||||
let vec: Vec<_> = vec![0];
|
||||
b.iter(|| vec.starts_with(&vec))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn starts_with_diff_one_element_at_end(b: &mut Bencher) {
|
||||
let vec: Vec<_> = (0..100).collect();
|
||||
let mut match_vec: Vec<_> = (0..99).collect();
|
||||
match_vec.push(0);
|
||||
b.iter(|| vec.starts_with(&match_vec))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn ends_with_same_vector(b: &mut Bencher) {
|
||||
let vec: Vec<_> = (0..100).collect();
|
||||
b.iter(|| vec.ends_with(&vec))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn ends_with_single_element(b: &mut Bencher) {
|
||||
let vec: Vec<_> = vec![0];
|
||||
b.iter(|| vec.ends_with(&vec))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) {
|
||||
let vec: Vec<_> = (0..100).collect();
|
||||
let mut match_vec: Vec<_> = (0..100).collect();
|
||||
match_vec[0] = 200;
|
||||
b.iter(|| vec.starts_with(&match_vec))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn contains_last_element(b: &mut Bencher) {
|
||||
let vec: Vec<_> = (0..100).collect();
|
||||
b.iter(|| vec.contains(&99))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn zero_1kb_from_elem(b: &mut Bencher) {
|
||||
b.iter(|| vec![0u8; 1024]);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn zero_1kb_set_memory(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let mut v = Vec::<u8>::with_capacity(1024);
|
||||
unsafe {
|
||||
let vp = v.as_mut_ptr();
|
||||
ptr::write_bytes(vp, 0, 1024);
|
||||
v.set_len(1024);
|
||||
}
|
||||
v
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn zero_1kb_loop_set(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let mut v = Vec::<u8>::with_capacity(1024);
|
||||
unsafe {
|
||||
v.set_len(1024);
|
||||
}
|
||||
for i in 0..1024 {
|
||||
v[i] = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn zero_1kb_mut_iter(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let mut v = Vec::<u8>::with_capacity(1024);
|
||||
unsafe {
|
||||
v.set_len(1024);
|
||||
}
|
||||
for x in &mut v {
|
||||
*x = 0;
|
||||
}
|
||||
v
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn random_inserts(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| {
|
||||
let mut v = vec![(0, 0); 30];
|
||||
for _ in 0..100 {
|
||||
let l = v.len();
|
||||
v.insert(rng.gen::<usize>() % (l + 1), (1, 1));
|
||||
}
|
||||
})
|
||||
}
|
||||
#[bench]
|
||||
fn random_removes(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| {
|
||||
let mut v = vec![(0, 0); 130];
|
||||
for _ in 0..100 {
|
||||
let l = v.len();
|
||||
v.remove(rng.gen::<usize>() % l);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn gen_ascending(len: usize) -> Vec<u64> {
|
||||
(0..len as u64).collect()
|
||||
}
|
||||
|
||||
fn gen_descending(len: usize) -> Vec<u64> {
|
||||
(0..len as u64).rev().collect()
|
||||
}
|
||||
|
||||
fn gen_random(len: usize) -> Vec<u64> {
|
||||
let mut rng = thread_rng();
|
||||
rng.gen_iter::<u64>().take(len).collect()
|
||||
}
|
||||
|
||||
fn gen_mostly_ascending(len: usize) -> Vec<u64> {
|
||||
let mut rng = thread_rng();
|
||||
let mut v = gen_ascending(len);
|
||||
for _ in (0usize..).take_while(|x| x * x <= len) {
|
||||
let x = rng.gen::<usize>() % len;
|
||||
let y = rng.gen::<usize>() % len;
|
||||
v.swap(x, y);
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
fn gen_mostly_descending(len: usize) -> Vec<u64> {
|
||||
let mut rng = thread_rng();
|
||||
let mut v = gen_descending(len);
|
||||
for _ in (0usize..).take_while(|x| x * x <= len) {
|
||||
let x = rng.gen::<usize>() % len;
|
||||
let y = rng.gen::<usize>() % len;
|
||||
v.swap(x, y);
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
fn gen_big_random(len: usize) -> Vec<[u64; 16]> {
|
||||
let mut rng = thread_rng();
|
||||
rng.gen_iter().map(|x| [x; 16]).take(len).collect()
|
||||
}
|
||||
|
||||
fn gen_big_ascending(len: usize) -> Vec<[u64; 16]> {
|
||||
(0..len as u64).map(|x| [x; 16]).take(len).collect()
|
||||
}
|
||||
|
||||
fn gen_big_descending(len: usize) -> Vec<[u64; 16]> {
|
||||
(0..len as u64).rev().map(|x| [x; 16]).take(len).collect()
|
||||
}
|
||||
|
||||
macro_rules! sort_bench {
|
||||
($name:ident, $gen:expr, $len:expr) => {
|
||||
#[bench]
|
||||
fn $name(b: &mut Bencher) {
|
||||
b.iter(|| $gen($len).sort());
|
||||
b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort_bench!(sort_small_random, gen_random, 10);
|
||||
sort_bench!(sort_small_ascending, gen_ascending, 10);
|
||||
sort_bench!(sort_small_descending, gen_descending, 10);
|
||||
|
||||
sort_bench!(sort_small_big_random, gen_big_random, 10);
|
||||
sort_bench!(sort_small_big_ascending, gen_big_ascending, 10);
|
||||
sort_bench!(sort_small_big_descending, gen_big_descending, 10);
|
||||
|
||||
sort_bench!(sort_medium_random, gen_random, 100);
|
||||
sort_bench!(sort_medium_ascending, gen_ascending, 100);
|
||||
sort_bench!(sort_medium_descending, gen_descending, 100);
|
||||
|
||||
sort_bench!(sort_large_random, gen_random, 10000);
|
||||
sort_bench!(sort_large_ascending, gen_ascending, 10000);
|
||||
sort_bench!(sort_large_descending, gen_descending, 10000);
|
||||
sort_bench!(sort_large_mostly_ascending, gen_mostly_ascending, 10000);
|
||||
sort_bench!(sort_large_mostly_descending, gen_mostly_descending, 10000);
|
||||
|
||||
sort_bench!(sort_large_big_random, gen_big_random, 10000);
|
||||
sort_bench!(sort_large_big_ascending, gen_big_ascending, 10000);
|
||||
sort_bench!(sort_large_big_descending, gen_big_descending, 10000);
|
||||
|
||||
#[bench]
|
||||
fn sort_large_random_expensive(b: &mut Bencher) {
|
||||
let len = 10000;
|
||||
b.iter(|| {
|
||||
let mut v = gen_random(len);
|
||||
let mut count = 0;
|
||||
v.sort_by(|a: &u64, b: &u64| {
|
||||
count += 1;
|
||||
if count % 1_000_000_000 == 0 {
|
||||
panic!("should not happen");
|
||||
}
|
||||
(*a as f64).cos().partial_cmp(&(*b as f64).cos()).unwrap()
|
||||
});
|
||||
black_box(count);
|
||||
});
|
||||
b.bytes = len as u64 * mem::size_of::<u64>() as u64;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1564,294 +1564,3 @@ fn different_str_pattern_forwarding_lifetimes() {
|
|||
|
||||
foo::<&str>("x");
|
||||
}
|
||||
|
||||
mod bench {
|
||||
use test::{Bencher, black_box};
|
||||
|
||||
#[bench]
|
||||
fn char_iterator(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
|
||||
b.iter(|| s.chars().count());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn char_iterator_for(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
|
||||
b.iter(|| {
|
||||
for ch in s.chars() { black_box(ch); }
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn char_iterator_ascii(b: &mut Bencher) {
|
||||
let s = "Mary had a little lamb, Little lamb
|
||||
Mary had a little lamb, Little lamb
|
||||
Mary had a little lamb, Little lamb
|
||||
Mary had a little lamb, Little lamb
|
||||
Mary had a little lamb, Little lamb
|
||||
Mary had a little lamb, Little lamb";
|
||||
|
||||
b.iter(|| s.chars().count());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn char_iterator_rev(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
|
||||
b.iter(|| s.chars().rev().count());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn char_iterator_rev_for(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
|
||||
b.iter(|| {
|
||||
for ch in s.chars().rev() { black_box(ch); }
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn char_indicesator(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
let len = s.chars().count();
|
||||
|
||||
b.iter(|| assert_eq!(s.char_indices().count(), len));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn char_indicesator_rev(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
let len = s.chars().count();
|
||||
|
||||
b.iter(|| assert_eq!(s.char_indices().rev().count(), len));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn split_unicode_ascii(b: &mut Bencher) {
|
||||
let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam";
|
||||
|
||||
b.iter(|| assert_eq!(s.split('V').count(), 3));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn split_ascii(b: &mut Bencher) {
|
||||
let s = "Mary had a little lamb, Little lamb, little-lamb.";
|
||||
let len = s.split(' ').count();
|
||||
|
||||
b.iter(|| assert_eq!(s.split(' ').count(), len));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn split_extern_fn(b: &mut Bencher) {
|
||||
let s = "Mary had a little lamb, Little lamb, little-lamb.";
|
||||
let len = s.split(' ').count();
|
||||
fn pred(c: char) -> bool { c == ' ' }
|
||||
|
||||
b.iter(|| assert_eq!(s.split(pred).count(), len));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn split_closure(b: &mut Bencher) {
|
||||
let s = "Mary had a little lamb, Little lamb, little-lamb.";
|
||||
let len = s.split(' ').count();
|
||||
|
||||
b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn split_slice(b: &mut Bencher) {
|
||||
let s = "Mary had a little lamb, Little lamb, little-lamb.";
|
||||
let len = s.split(' ').count();
|
||||
|
||||
let c: &[char] = &[' '];
|
||||
b.iter(|| assert_eq!(s.split(c).count(), len));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_join(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
let sep = "→";
|
||||
let v = vec![s, s, s, s, s, s, s, s, s, s];
|
||||
b.iter(|| {
|
||||
assert_eq!(v.join(sep).len(), s.len() * 10 + sep.len() * 9);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_contains_short_short(b: &mut Bencher) {
|
||||
let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
|
||||
let needle = "sit";
|
||||
|
||||
b.iter(|| {
|
||||
assert!(haystack.contains(needle));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_contains_short_long(b: &mut Bencher) {
|
||||
let haystack = "\
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
|
||||
ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
|
||||
eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
|
||||
sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
|
||||
tempus vel, gravida nec quam.
|
||||
|
||||
In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \
|
||||
sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \
|
||||
diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \
|
||||
lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \
|
||||
eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \
|
||||
interdum. Curabitur ut nisi justo.
|
||||
|
||||
Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \
|
||||
mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \
|
||||
lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \
|
||||
est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \
|
||||
felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \
|
||||
ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \
|
||||
feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \
|
||||
Aliquam sit amet placerat lorem.
|
||||
|
||||
Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \
|
||||
mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \
|
||||
Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \
|
||||
lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \
|
||||
suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \
|
||||
cursus accumsan.
|
||||
|
||||
Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \
|
||||
feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
|
||||
vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
|
||||
leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
|
||||
malesuada sollicitudin quam eu fermentum.";
|
||||
let needle = "english";
|
||||
|
||||
b.iter(|| {
|
||||
assert!(!haystack.contains(needle));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_contains_bad_naive(b: &mut Bencher) {
|
||||
let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||
let needle = "aaaaaaaab";
|
||||
|
||||
b.iter(|| {
|
||||
assert!(!haystack.contains(needle));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_contains_equal(b: &mut Bencher) {
|
||||
let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
|
||||
let needle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
|
||||
|
||||
b.iter(|| {
|
||||
assert!(haystack.contains(needle));
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! make_test_inner {
|
||||
($s:ident, $code:expr, $name:ident, $str:expr) => {
|
||||
#[bench]
|
||||
fn $name(bencher: &mut Bencher) {
|
||||
let mut $s = $str;
|
||||
black_box(&mut $s);
|
||||
bencher.iter(|| $code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! make_test {
|
||||
($name:ident, $s:ident, $code:expr) => {
|
||||
mod $name {
|
||||
use test::Bencher;
|
||||
use test::black_box;
|
||||
|
||||
// Short strings: 65 bytes each
|
||||
make_test_inner!($s, $code, short_ascii,
|
||||
"Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!");
|
||||
make_test_inner!($s, $code, short_mixed,
|
||||
"ศไทย中华Việt Nam; Mary had a little lamb, Little lam!");
|
||||
make_test_inner!($s, $code, short_pile_of_poo,
|
||||
"💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!");
|
||||
make_test_inner!($s, $code, long_lorem_ipsum,"\
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
|
||||
ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
|
||||
eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
|
||||
sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
|
||||
tempus vel, gravida nec quam.
|
||||
|
||||
In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \
|
||||
sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \
|
||||
diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \
|
||||
lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \
|
||||
eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \
|
||||
interdum. Curabitur ut nisi justo.
|
||||
|
||||
Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \
|
||||
mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \
|
||||
lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \
|
||||
est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \
|
||||
felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \
|
||||
ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \
|
||||
feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \
|
||||
Aliquam sit amet placerat lorem.
|
||||
|
||||
Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \
|
||||
mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \
|
||||
Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \
|
||||
lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \
|
||||
suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \
|
||||
cursus accumsan.
|
||||
|
||||
Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \
|
||||
feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
|
||||
vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
|
||||
leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
|
||||
malesuada sollicitudin quam eu fermentum!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
make_test!(chars_count, s, s.chars().count());
|
||||
|
||||
make_test!(contains_bang_str, s, s.contains("!"));
|
||||
make_test!(contains_bang_char, s, s.contains('!'));
|
||||
|
||||
make_test!(match_indices_a_str, s, s.match_indices("a").count());
|
||||
|
||||
make_test!(split_a_str, s, s.split("a").count());
|
||||
|
||||
make_test!(trim_ascii_char, s, {
|
||||
use std::ascii::AsciiExt;
|
||||
s.trim_matches(|c: char| c.is_ascii())
|
||||
});
|
||||
make_test!(trim_left_ascii_char, s, {
|
||||
use std::ascii::AsciiExt;
|
||||
s.trim_left_matches(|c: char| c.is_ascii())
|
||||
});
|
||||
make_test!(trim_right_ascii_char, s, {
|
||||
use std::ascii::AsciiExt;
|
||||
s.trim_right_matches(|c: char| c.is_ascii())
|
||||
});
|
||||
|
||||
make_test!(find_underscore_char, s, s.find('_'));
|
||||
make_test!(rfind_underscore_char, s, s.rfind('_'));
|
||||
make_test!(find_underscore_str, s, s.find("_"));
|
||||
|
||||
make_test!(find_zzz_char, s, s.find('\u{1F4A4}'));
|
||||
make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}'));
|
||||
make_test!(find_zzz_str, s, s.find("\u{1F4A4}"));
|
||||
|
||||
make_test!(split_space_char, s, s.split(' ').count());
|
||||
make_test!(split_terminator_space_char, s, s.split_terminator(' ').count());
|
||||
|
||||
make_test!(splitn_space_char, s, s.splitn(10, ' ').count());
|
||||
make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count());
|
||||
|
||||
make_test!(split_space_str, s, s.split(" ").count());
|
||||
make_test!(split_ad_str, s, s.split("ad").count());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,6 @@
|
|||
// except according to those terms.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::iter::repeat;
|
||||
|
||||
use test::Bencher;
|
||||
|
||||
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
|
||||
fn into_cow(self) -> Cow<'a, B>;
|
||||
|
|
@ -436,125 +433,3 @@ fn test_into_boxed_str() {
|
|||
let ys = xs.into_boxed_str();
|
||||
assert_eq!(&*ys, "hello my name is bob");
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_with_capacity(b: &mut Bencher) {
|
||||
b.iter(|| String::with_capacity(100));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_str(b: &mut Bencher) {
|
||||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||||
b.iter(|| {
|
||||
let mut r = String::new();
|
||||
r.push_str(s);
|
||||
});
|
||||
}
|
||||
|
||||
const REPETITIONS: u64 = 10_000;
|
||||
|
||||
#[bench]
|
||||
fn bench_push_str_one_byte(b: &mut Bencher) {
|
||||
b.bytes = REPETITIONS;
|
||||
b.iter(|| {
|
||||
let mut r = String::new();
|
||||
for _ in 0..REPETITIONS {
|
||||
r.push_str("a")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_char_one_byte(b: &mut Bencher) {
|
||||
b.bytes = REPETITIONS;
|
||||
b.iter(|| {
|
||||
let mut r = String::new();
|
||||
for _ in 0..REPETITIONS {
|
||||
r.push('a')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_char_two_bytes(b: &mut Bencher) {
|
||||
b.bytes = REPETITIONS * 2;
|
||||
b.iter(|| {
|
||||
let mut r = String::new();
|
||||
for _ in 0..REPETITIONS {
|
||||
r.push('â')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn from_utf8_lossy_100_ascii(b: &mut Bencher) {
|
||||
let s = b"Hello there, the quick brown fox jumped over the lazy dog! \
|
||||
Lorem ipsum dolor sit amet, consectetur. ";
|
||||
|
||||
assert_eq!(100, s.len());
|
||||
b.iter(|| {
|
||||
let _ = String::from_utf8_lossy(s);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn from_utf8_lossy_100_multibyte(b: &mut Bencher) {
|
||||
let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes();
|
||||
assert_eq!(100, s.len());
|
||||
b.iter(|| {
|
||||
let _ = String::from_utf8_lossy(s);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn from_utf8_lossy_invalid(b: &mut Bencher) {
|
||||
let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
|
||||
b.iter(|| {
|
||||
let _ = String::from_utf8_lossy(s);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn from_utf8_lossy_100_invalid(b: &mut Bencher) {
|
||||
let s = repeat(0xf5).take(100).collect::<Vec<_>>();
|
||||
b.iter(|| {
|
||||
let _ = String::from_utf8_lossy(&s);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_exact_size_shrink_to_fit(b: &mut Bencher) {
|
||||
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
|
||||
Lorem ipsum dolor sit amet, consectetur. ";
|
||||
// ensure our operation produces an exact-size string before we benchmark it
|
||||
let mut r = String::with_capacity(s.len());
|
||||
r.push_str(s);
|
||||
assert_eq!(r.len(), r.capacity());
|
||||
b.iter(|| {
|
||||
let mut r = String::with_capacity(s.len());
|
||||
r.push_str(s);
|
||||
r.shrink_to_fit();
|
||||
r
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_str(b: &mut Bencher) {
|
||||
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
|
||||
Lorem ipsum dolor sit amet, consectetur. ";
|
||||
b.iter(|| String::from(s))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from(b: &mut Bencher) {
|
||||
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
|
||||
Lorem ipsum dolor sit amet, consectetur. ";
|
||||
b.iter(|| String::from(s))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_to_string(b: &mut Bencher) {
|
||||
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
|
||||
Lorem ipsum dolor sit amet, consectetur. ";
|
||||
b.iter(|| s.to_string())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,13 +10,10 @@
|
|||
|
||||
use std::ascii::AsciiExt;
|
||||
use std::borrow::Cow;
|
||||
use std::iter::{FromIterator, repeat};
|
||||
use std::mem::size_of;
|
||||
use std::panic;
|
||||
use std::vec::{Drain, IntoIter};
|
||||
|
||||
use test::Bencher;
|
||||
|
||||
struct DropCounter<'a> {
|
||||
count: &'a mut u32,
|
||||
}
|
||||
|
|
@ -633,483 +630,3 @@ fn test_placement_panic() {
|
|||
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { vec.place_back() <- mkpanic(); }));
|
||||
assert_eq!(vec.len(), 3);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_new(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let v: Vec<u32> = Vec::new();
|
||||
assert_eq!(v.len(), 0);
|
||||
assert_eq!(v.capacity(), 0);
|
||||
})
|
||||
}
|
||||
|
||||
fn do_bench_with_capacity(b: &mut Bencher, src_len: usize) {
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let v: Vec<u32> = Vec::with_capacity(src_len);
|
||||
assert_eq!(v.len(), 0);
|
||||
assert_eq!(v.capacity(), src_len);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_with_capacity_0000(b: &mut Bencher) {
|
||||
do_bench_with_capacity(b, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_with_capacity_0010(b: &mut Bencher) {
|
||||
do_bench_with_capacity(b, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_with_capacity_0100(b: &mut Bencher) {
|
||||
do_bench_with_capacity(b, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_with_capacity_1000(b: &mut Bencher) {
|
||||
do_bench_with_capacity(b, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_from_fn(b: &mut Bencher, src_len: usize) {
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let dst = (0..src_len).collect::<Vec<_>>();
|
||||
assert_eq!(dst.len(), src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_fn_0000(b: &mut Bencher) {
|
||||
do_bench_from_fn(b, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_fn_0010(b: &mut Bencher) {
|
||||
do_bench_from_fn(b, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_fn_0100(b: &mut Bencher) {
|
||||
do_bench_from_fn(b, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_fn_1000(b: &mut Bencher) {
|
||||
do_bench_from_fn(b, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_from_elem(b: &mut Bencher, src_len: usize) {
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let dst: Vec<usize> = repeat(5).take(src_len).collect();
|
||||
assert_eq!(dst.len(), src_len);
|
||||
assert!(dst.iter().all(|x| *x == 5));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_elem_0000(b: &mut Bencher) {
|
||||
do_bench_from_elem(b, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_elem_0010(b: &mut Bencher) {
|
||||
do_bench_from_elem(b, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_elem_0100(b: &mut Bencher) {
|
||||
do_bench_from_elem(b, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_elem_1000(b: &mut Bencher) {
|
||||
do_bench_from_elem(b, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_from_slice(b: &mut Bencher, src_len: usize) {
|
||||
let src: Vec<_> = FromIterator::from_iter(0..src_len);
|
||||
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let dst = src.clone()[..].to_vec();
|
||||
assert_eq!(dst.len(), src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_slice_0000(b: &mut Bencher) {
|
||||
do_bench_from_slice(b, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_slice_0010(b: &mut Bencher) {
|
||||
do_bench_from_slice(b, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_slice_0100(b: &mut Bencher) {
|
||||
do_bench_from_slice(b, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_slice_1000(b: &mut Bencher) {
|
||||
do_bench_from_slice(b, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_from_iter(b: &mut Bencher, src_len: usize) {
|
||||
let src: Vec<_> = FromIterator::from_iter(0..src_len);
|
||||
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let dst: Vec<_> = FromIterator::from_iter(src.clone());
|
||||
assert_eq!(dst.len(), src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_iter_0000(b: &mut Bencher) {
|
||||
do_bench_from_iter(b, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_iter_0010(b: &mut Bencher) {
|
||||
do_bench_from_iter(b, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_iter_0100(b: &mut Bencher) {
|
||||
do_bench_from_iter(b, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_from_iter_1000(b: &mut Bencher) {
|
||||
do_bench_from_iter(b, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_extend(b: &mut Bencher, dst_len: usize, src_len: usize) {
|
||||
let dst: Vec<_> = FromIterator::from_iter(0..dst_len);
|
||||
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
|
||||
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let mut dst = dst.clone();
|
||||
dst.extend(src.clone());
|
||||
assert_eq!(dst.len(), dst_len + src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_extend_0000_0000(b: &mut Bencher) {
|
||||
do_bench_extend(b, 0, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_extend_0000_0010(b: &mut Bencher) {
|
||||
do_bench_extend(b, 0, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_extend_0000_0100(b: &mut Bencher) {
|
||||
do_bench_extend(b, 0, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_extend_0000_1000(b: &mut Bencher) {
|
||||
do_bench_extend(b, 0, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_extend_0010_0010(b: &mut Bencher) {
|
||||
do_bench_extend(b, 10, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_extend_0100_0100(b: &mut Bencher) {
|
||||
do_bench_extend(b, 100, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_extend_1000_1000(b: &mut Bencher) {
|
||||
do_bench_extend(b, 1000, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_push_all(b: &mut Bencher, dst_len: usize, src_len: usize) {
|
||||
let dst: Vec<_> = FromIterator::from_iter(0..dst_len);
|
||||
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
|
||||
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let mut dst = dst.clone();
|
||||
dst.extend_from_slice(&src);
|
||||
assert_eq!(dst.len(), dst_len + src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_0000_0000(b: &mut Bencher) {
|
||||
do_bench_push_all(b, 0, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_0000_0010(b: &mut Bencher) {
|
||||
do_bench_push_all(b, 0, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_0000_0100(b: &mut Bencher) {
|
||||
do_bench_push_all(b, 0, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_0000_1000(b: &mut Bencher) {
|
||||
do_bench_push_all(b, 0, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_0010_0010(b: &mut Bencher) {
|
||||
do_bench_push_all(b, 10, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_0100_0100(b: &mut Bencher) {
|
||||
do_bench_push_all(b, 100, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_1000_1000(b: &mut Bencher) {
|
||||
do_bench_push_all(b, 1000, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_push_all_move(b: &mut Bencher, dst_len: usize, src_len: usize) {
|
||||
let dst: Vec<_> = FromIterator::from_iter(0..dst_len);
|
||||
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
|
||||
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let mut dst = dst.clone();
|
||||
dst.extend(src.clone());
|
||||
assert_eq!(dst.len(), dst_len + src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_move_0000_0000(b: &mut Bencher) {
|
||||
do_bench_push_all_move(b, 0, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_move_0000_0010(b: &mut Bencher) {
|
||||
do_bench_push_all_move(b, 0, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_move_0000_0100(b: &mut Bencher) {
|
||||
do_bench_push_all_move(b, 0, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_move_0000_1000(b: &mut Bencher) {
|
||||
do_bench_push_all_move(b, 0, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_move_0010_0010(b: &mut Bencher) {
|
||||
do_bench_push_all_move(b, 10, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_move_0100_0100(b: &mut Bencher) {
|
||||
do_bench_push_all_move(b, 100, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_push_all_move_1000_1000(b: &mut Bencher) {
|
||||
do_bench_push_all_move(b, 1000, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_clone(b: &mut Bencher, src_len: usize) {
|
||||
let src: Vec<usize> = FromIterator::from_iter(0..src_len);
|
||||
|
||||
b.bytes = src_len as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let dst = src.clone();
|
||||
assert_eq!(dst.len(), src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_0000(b: &mut Bencher) {
|
||||
do_bench_clone(b, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_0010(b: &mut Bencher) {
|
||||
do_bench_clone(b, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_0100(b: &mut Bencher) {
|
||||
do_bench_clone(b, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_1000(b: &mut Bencher) {
|
||||
do_bench_clone(b, 1000)
|
||||
}
|
||||
|
||||
fn do_bench_clone_from(b: &mut Bencher, times: usize, dst_len: usize, src_len: usize) {
|
||||
let dst: Vec<_> = FromIterator::from_iter(0..src_len);
|
||||
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
|
||||
|
||||
b.bytes = (times * src_len) as u64;
|
||||
|
||||
b.iter(|| {
|
||||
let mut dst = dst.clone();
|
||||
|
||||
for _ in 0..times {
|
||||
dst.clone_from(&src);
|
||||
|
||||
assert_eq!(dst.len(), src_len);
|
||||
assert!(dst.iter().enumerate().all(|(i, x)| dst_len + i == *x));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0000_0000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 0, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0000_0010(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 0, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0000_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 0, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0000_1000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 0, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0010_0010(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 10, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0100_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 100, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_1000_1000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 1000, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0010_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 10, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0100_1000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 100, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0010_0000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 10, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_0100_0010(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 100, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_01_1000_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 1, 1000, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0000_0000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 0, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0000_0010(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 0, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0000_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 0, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0000_1000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 0, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0010_0010(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 10, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0100_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 100, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_1000_1000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 1000, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0010_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 10, 100)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0100_1000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 100, 1000)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0010_0000(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 10, 0)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_0100_0010(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 100, 10)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_clone_from_10_1000_0100(b: &mut Bencher) {
|
||||
do_bench_clone_from(b, 10, 1000, 100)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ use std::collections::VecDeque;
|
|||
use std::fmt::Debug;
|
||||
use std::collections::vec_deque::Drain;
|
||||
|
||||
use test;
|
||||
|
||||
use self::Taggy::*;
|
||||
use self::Taggypar::*;
|
||||
|
||||
|
|
@ -124,51 +122,6 @@ fn test_index_out_of_bounds() {
|
|||
deq[3];
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_new(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let ring: VecDeque<i32> = VecDeque::new();
|
||||
test::black_box(ring);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_grow_1025(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let mut deq = VecDeque::new();
|
||||
for i in 0..1025 {
|
||||
deq.push_front(i);
|
||||
}
|
||||
test::black_box(deq);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_iter_1000(b: &mut test::Bencher) {
|
||||
let ring: VecDeque<_> = (0..1000).collect();
|
||||
|
||||
b.iter(|| {
|
||||
let mut sum = 0;
|
||||
for &i in &ring {
|
||||
sum += i;
|
||||
}
|
||||
test::black_box(sum);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_mut_iter_1000(b: &mut test::Bencher) {
|
||||
let mut ring: VecDeque<_> = (0..1000).collect();
|
||||
|
||||
b.iter(|| {
|
||||
let mut sum = 0;
|
||||
for i in &mut ring {
|
||||
sum += *i;
|
||||
}
|
||||
test::black_box(sum);
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
enum Taggy {
|
||||
One(i32),
|
||||
|
|
|
|||
|
|
@ -14,5 +14,5 @@ name = "coretest"
|
|||
path = "../libcoretest/lib.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "corebench"
|
||||
path = "../libcore/bench/lib.rs"
|
||||
name = "corebenches"
|
||||
path = "../libcore/benches/lib.rs"
|
||||
|
|
|
|||
|
|
@ -1318,24 +1318,6 @@ atomic_int! {
|
|||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
u64 AtomicU64 ATOMIC_U64_INIT
|
||||
}
|
||||
#[cfg(not(stage0))]
|
||||
#[cfg(target_has_atomic = "128")]
|
||||
atomic_int! {
|
||||
unstable(feature = "i128", issue = "35118"),
|
||||
unstable(feature = "i128", issue = "35118"),
|
||||
unstable(feature = "i128", issue = "35118"),
|
||||
unstable(feature = "i128", issue = "35118"),
|
||||
i128 AtomicI128 ATOMIC_I128_INIT
|
||||
}
|
||||
#[cfg(not(stage0))]
|
||||
#[cfg(target_has_atomic = "128")]
|
||||
atomic_int! {
|
||||
unstable(feature = "i128", issue = "35118"),
|
||||
unstable(feature = "i128", issue = "35118"),
|
||||
unstable(feature = "i128", issue = "35118"),
|
||||
unstable(feature = "i128", issue = "35118"),
|
||||
u128 AtomicU128 ATOMIC_U128_INIT
|
||||
}
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
atomic_int!{
|
||||
stable(feature = "rust1", since = "1.0.0"),
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
extern crate gcc;
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rustc-cfg=cargobuild");
|
||||
gcc::Config::new()
|
||||
.file("../rt/miniz.c")
|
||||
.compile("libminiz.a");
|
||||
|
|
|
|||
|
|
@ -74,10 +74,6 @@ impl Drop for Bytes {
|
|||
}
|
||||
}
|
||||
|
||||
#[link(name = "miniz", kind = "static")]
|
||||
#[cfg(not(cargobuild))]
|
||||
extern "C" {}
|
||||
|
||||
extern "C" {
|
||||
/// Raw miniz compression function.
|
||||
fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void,
|
||||
|
|
|
|||
|
|
@ -301,10 +301,6 @@ unsafe extern "C" fn rust_eh_unwind_resume(panic_ctx: *mut u8) -> ! {
|
|||
// with any GCC runtime.
|
||||
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
|
||||
pub mod eh_frame_registry {
|
||||
#[link(name = "gcc_eh")]
|
||||
#[cfg(not(cargobuild))]
|
||||
extern "C" {}
|
||||
|
||||
extern "C" {
|
||||
fn __register_frame_info(eh_frame_begin: *const u8, object: *mut u8);
|
||||
fn __deregister_frame_info(eh_frame_begin: *const u8, object: *mut u8);
|
||||
|
|
|
|||
|
|
@ -229,6 +229,7 @@ pub trait CrateStore<'tcx> {
|
|||
fn is_allocator(&self, cnum: CrateNum) -> bool;
|
||||
fn is_panic_runtime(&self, cnum: CrateNum) -> bool;
|
||||
fn is_compiler_builtins(&self, cnum: CrateNum) -> bool;
|
||||
fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool;
|
||||
fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy;
|
||||
fn extern_crate(&self, cnum: CrateNum) -> Option<ExternCrate>;
|
||||
/// The name of the crate as it is referred to in source code of the current
|
||||
|
|
@ -390,6 +391,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
|||
fn is_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") }
|
||||
fn is_panic_runtime(&self, cnum: CrateNum) -> bool { bug!("is_panic_runtime") }
|
||||
fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") }
|
||||
fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool { bug!("is_sanitizer_runtime") }
|
||||
fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
|
||||
bug!("panic_strategy")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ macro_rules! newtype_index {
|
|||
}
|
||||
|
||||
/// Lowered representation of a single function.
|
||||
// Do not implement clone for Mir, its easy to do so accidently and its kind of expensive.
|
||||
// Do not implement clone for Mir, which can be accidently done and kind of expensive.
|
||||
#[derive(RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct Mir<'tcx> {
|
||||
/// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
|
||||
|
|
|
|||
|
|
@ -51,6 +51,14 @@ pub struct Config {
|
|||
pub uint_type: UintTy,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Sanitizer {
|
||||
Address,
|
||||
Leak,
|
||||
Memory,
|
||||
Thread,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Hash)]
|
||||
pub enum OptLevel {
|
||||
No, // -O0
|
||||
|
|
@ -626,11 +634,13 @@ macro_rules! options {
|
|||
Some("a number");
|
||||
pub const parse_panic_strategy: Option<&'static str> =
|
||||
Some("either `panic` or `abort`");
|
||||
pub const parse_sanitizer: Option<&'static str> =
|
||||
Some("one of: `address`, `leak`, `memory` or `thread`");
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod $mod_set {
|
||||
use super::{$struct_name, Passes, SomePasses, AllPasses};
|
||||
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer};
|
||||
use rustc_back::PanicStrategy;
|
||||
|
||||
$(
|
||||
|
|
@ -751,6 +761,17 @@ macro_rules! options {
|
|||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn parse_sanitizer(slote: &mut Option<Sanitizer>, v: Option<&str>) -> bool {
|
||||
match v {
|
||||
Some("address") => *slote = Some(Sanitizer::Address),
|
||||
Some("leak") => *slote = Some(Sanitizer::Leak),
|
||||
Some("memory") => *slote = Some(Sanitizer::Memory),
|
||||
Some("thread") => *slote = Some(Sanitizer::Thread),
|
||||
_ => return false,
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
) }
|
||||
|
||||
|
|
@ -949,6 +970,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
"encode MIR of all functions into the crate metadata"),
|
||||
osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
|
||||
"pass `-install_name @rpath/...` to the OSX linker"),
|
||||
sanitizer: Option<Sanitizer> = (None, parse_sanitizer, [UNTRACKED],
|
||||
"Use a sanitizer"),
|
||||
}
|
||||
|
||||
pub fn default_lib_output() -> CrateType {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ use util::nodemap::{FxHashMap, FxHashSet};
|
|||
use std::cmp;
|
||||
use std::fmt;
|
||||
use syntax::ast;
|
||||
use hir::{intravisit, Local, Pat};
|
||||
use hir::intravisit::{Visitor, NestedVisitorMap};
|
||||
use syntax_pos::{DUMMY_SP, Span};
|
||||
use errors::DiagnosticBuilder;
|
||||
|
||||
|
|
@ -60,6 +62,30 @@ impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||
target_ty: &'a Ty<'tcx>,
|
||||
found_pattern: Option<&'a Pat>,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Visitor<'a> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
|
||||
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
|
||||
NestedVisitorMap::None
|
||||
}
|
||||
|
||||
fn visit_local(&mut self, local: &'a Local) {
|
||||
if let Some(&ty) = self.infcx.tables.borrow().node_types.get(&local.id) {
|
||||
let ty = self.infcx.resolve_type_vars_if_possible(&ty);
|
||||
let is_match = ty.walk().any(|t| t == *self.target_ty);
|
||||
|
||||
if is_match && self.found_pattern.is_none() {
|
||||
self.found_pattern = Some(&*local.pat);
|
||||
}
|
||||
}
|
||||
intravisit::walk_local(self, local);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn report_fulfillment_errors(&self, errors: &Vec<FulfillmentError<'tcx>>) {
|
||||
for error in errors {
|
||||
|
|
@ -775,7 +801,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
self.tcx.lang_items.sized_trait()
|
||||
.map_or(false, |sized_id| sized_id == trait_ref.def_id())
|
||||
{
|
||||
self.need_type_info(obligation.cause.span, self_ty);
|
||||
self.need_type_info(obligation, self_ty);
|
||||
} else {
|
||||
let mut err = struct_span_err!(self.tcx.sess,
|
||||
obligation.cause.span, E0283,
|
||||
|
|
@ -793,7 +819,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
// Same hacky approach as above to avoid deluging user
|
||||
// with error messages.
|
||||
if !ty.references_error() && !self.tcx.sess.has_errors() {
|
||||
self.need_type_info(obligation.cause.span, ty);
|
||||
self.need_type_info(obligation, ty);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -857,27 +883,53 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
|
||||
fn need_type_info(&self, span: Span, ty: Ty<'tcx>) {
|
||||
let ty = self.resolve_type_vars_if_possible(&ty);
|
||||
let name = if let ty::TyInfer(ty::TyVar(ty_vid)) = ty.sty {
|
||||
fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String {
|
||||
if let ty::TyInfer(ty::TyVar(ty_vid)) = (*ty).sty {
|
||||
let ty_vars = self.type_variables.borrow();
|
||||
if let TypeVariableOrigin::TypeParameterDefinition(_, name) =
|
||||
*ty_vars.var_origin(ty_vid)
|
||||
{
|
||||
*ty_vars.var_origin(ty_vid) {
|
||||
name.to_string()
|
||||
} else {
|
||||
ty.to_string()
|
||||
}
|
||||
} else {
|
||||
ty.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
fn need_type_info(&self, obligation: &PredicateObligation<'tcx>, ty: Ty<'tcx>) {
|
||||
let ty = self.resolve_type_vars_if_possible(&ty);
|
||||
let name = self.extract_type_name(&ty);
|
||||
let ref cause = obligation.cause;
|
||||
|
||||
let mut err = struct_span_err!(self.tcx.sess,
|
||||
cause.span,
|
||||
E0282,
|
||||
"type annotations needed");
|
||||
|
||||
err.span_label(cause.span, &format!("cannot infer type for `{}`", name));
|
||||
|
||||
let expr = self.tcx.hir.expect_expr(cause.body_id);
|
||||
|
||||
let mut local_visitor = FindLocalByTypeVisitor {
|
||||
infcx: &self,
|
||||
target_ty: &ty,
|
||||
found_pattern: None,
|
||||
};
|
||||
|
||||
let mut err = struct_span_err!(self.tcx.sess, span, E0282,
|
||||
"unable to infer enough type information about `{}`",
|
||||
name);
|
||||
err.note("type annotations or generic parameter binding required");
|
||||
err.span_label(span, &format!("cannot infer type for `{}`", name));
|
||||
local_visitor.visit_expr(expr);
|
||||
|
||||
if let Some(pattern) = local_visitor.found_pattern {
|
||||
let pattern_span = pattern.span;
|
||||
if let Some(simple_name) = pattern.simple_name() {
|
||||
err.span_label(pattern_span,
|
||||
&format!("consider giving `{}` a type",
|
||||
simple_name));
|
||||
} else {
|
||||
err.span_label(pattern_span, &format!("consider giving a type to pattern"));
|
||||
}
|
||||
}
|
||||
|
||||
err.emit();
|
||||
}
|
||||
|
||||
|
|
|
|||
17
src/librustc_asan/Cargo.toml
Normal file
17
src/librustc_asan/Cargo.toml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
[package]
|
||||
authors = ["The Rust Project Developers"]
|
||||
build = "build.rs"
|
||||
name = "rustc_asan"
|
||||
version = "0.0.0"
|
||||
|
||||
[lib]
|
||||
name = "rustc_asan"
|
||||
path = "lib.rs"
|
||||
|
||||
[build-dependencies]
|
||||
build_helper = { path = "../build_helper" }
|
||||
cmake = "0.1.18"
|
||||
|
||||
[dependencies]
|
||||
alloc_system = { path = "../liballoc_system" }
|
||||
core = { path = "../libcore" }
|
||||
39
src/librustc_asan/build.rs
Normal file
39
src/librustc_asan/build.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// 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.
|
||||
|
||||
extern crate build_helper;
|
||||
extern crate cmake;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::env;
|
||||
|
||||
use cmake::Config;
|
||||
|
||||
fn main() {
|
||||
if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
|
||||
let dst = Config::new("../compiler-rt")
|
||||
.define("COMPILER_RT_BUILD_SANITIZERS", "ON")
|
||||
.define("COMPILER_RT_BUILD_BUILTINS", "OFF")
|
||||
.define("COMPILER_RT_BUILD_XRAY", "OFF")
|
||||
.define("LLVM_CONFIG_PATH", llvm_config)
|
||||
.build_target("asan")
|
||||
.build();
|
||||
|
||||
println!("cargo:rustc-link-search=native={}",
|
||||
dst.join("build/lib/linux").display());
|
||||
println!("cargo:rustc-link-lib=static=clang_rt.asan-x86_64");
|
||||
|
||||
build_helper::rerun_if_changed_anything_in_dir(&PathBuf::from(env::var("CARGO_MANIFEST_DIR")
|
||||
.unwrap())
|
||||
.join("../compiler-rt"));
|
||||
}
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
}
|
||||
20
src/librustc_asan/lib.rs
Normal file
20
src/librustc_asan/lib.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// 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.
|
||||
|
||||
#![cfg_attr(not(stage0), feature(sanitizer_runtime))]
|
||||
#![cfg_attr(not(stage0), sanitizer_runtime)]
|
||||
#![feature(alloc_system)]
|
||||
#![feature(staged_api)]
|
||||
#![no_std]
|
||||
#![unstable(feature = "sanitizer_runtime_lib",
|
||||
reason = "internal implementation detail of sanitizers",
|
||||
issue = "0")]
|
||||
|
||||
extern crate alloc_system;
|
||||
30
src/librustc_back/target/i686_unknown_netbsd.rs
Normal file
30
src/librustc_back/target/i686_unknown_netbsd.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2017 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 target::{Target, TargetResult};
|
||||
|
||||
pub fn target() -> TargetResult {
|
||||
let mut base = super::netbsd_base::opts();
|
||||
base.cpu = "pentium4".to_string();
|
||||
base.max_atomic_width = Some(64);
|
||||
base.pre_link_args.push("-m32".to_string());
|
||||
|
||||
Ok(Target {
|
||||
llvm_target: "i686-unknown-netbsdelf".to_string(),
|
||||
target_endian: "little".to_string(),
|
||||
target_pointer_width: "32".to_string(),
|
||||
data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
|
||||
arch: "x86".to_string(),
|
||||
target_os: "netbsd".to_string(),
|
||||
target_env: "".to_string(),
|
||||
target_vendor: "unknown".to_string(),
|
||||
options: base,
|
||||
})
|
||||
}
|
||||
|
|
@ -177,6 +177,7 @@ supported_targets! {
|
|||
("i686-unknown-openbsd", i686_unknown_openbsd),
|
||||
("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
|
||||
|
||||
("i686-unknown-netbsd", i686_unknown_netbsd),
|
||||
("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
|
||||
("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
|
||||
("x86_64-rumprun-netbsd", x86_64_rumprun_netbsd),
|
||||
|
|
|
|||
|
|
@ -176,46 +176,32 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
// Recreate the edges in the graph that are still clean.
|
||||
let mut clean_work_products = FxHashSet();
|
||||
let mut dirty_work_products = FxHashSet(); // incomplete; just used to suppress debug output
|
||||
let mut extra_edges = vec![];
|
||||
for (source, targets) in &edge_map {
|
||||
for target in targets {
|
||||
// If the target is dirty, skip the edge. If this is an edge
|
||||
// that targets a work-product, we can print the blame
|
||||
// information now.
|
||||
if let Some(blame) = dirty_raw_nodes.get(target) {
|
||||
if let DepNode::WorkProduct(ref wp) = *target {
|
||||
if tcx.sess.opts.debugging_opts.incremental_info {
|
||||
if dirty_work_products.insert(wp.clone()) {
|
||||
// It'd be nice to pretty-print these paths better than just
|
||||
// using the `Debug` impls, but wev.
|
||||
println!("incremental: module {:?} is dirty because {:?} \
|
||||
changed or was removed",
|
||||
wp,
|
||||
blame.map_def(|&index| {
|
||||
Some(directory.def_path_string(tcx, index))
|
||||
}).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the source is dirty, the target will be dirty.
|
||||
assert!(!dirty_raw_nodes.contains_key(source));
|
||||
|
||||
// Retrace the source -> target edges to def-ids and then
|
||||
// create an edge in the graph. Retracing may yield none if
|
||||
// some of the data happens to have been removed; this ought
|
||||
// to be impossible unless it is dirty, so we can unwrap.
|
||||
let source_node = retraced.map(source).unwrap();
|
||||
let target_node = retraced.map(target).unwrap();
|
||||
let _task = tcx.dep_graph.in_task(target_node);
|
||||
tcx.dep_graph.read(source_node);
|
||||
if let DepNode::WorkProduct(ref wp) = *target {
|
||||
clean_work_products.insert(wp.clone());
|
||||
}
|
||||
process_edges(tcx, source, target, &edge_map, &directory, &retraced, &dirty_raw_nodes,
|
||||
&mut clean_work_products, &mut dirty_work_products, &mut extra_edges);
|
||||
}
|
||||
}
|
||||
|
||||
// Subtle. Sometimes we have intermediate nodes that we can't recreate in the new graph.
|
||||
// This is pretty unusual but it arises in a scenario like this:
|
||||
//
|
||||
// Hir(X) -> Foo(Y) -> Bar
|
||||
//
|
||||
// Note that the `Hir(Y)` is not an input to `Foo(Y)` -- this
|
||||
// almost never happens, but can happen in some obscure
|
||||
// scenarios. In that case, if `Y` is removed, then we can't
|
||||
// recreate `Foo(Y)` (the def-id `Y` no longer exists); what we do
|
||||
// then is to push the edge `Hir(X) -> Bar` onto `extra_edges`
|
||||
// (along with any other targets of `Foo(Y)`). We will then add
|
||||
// the edge from `Hir(X)` to `Bar` (or, if `Bar` itself cannot be
|
||||
// recreated, to the targets of `Bar`).
|
||||
while let Some((source, target)) = extra_edges.pop() {
|
||||
process_edges(tcx, source, target, &edge_map, &directory, &retraced, &dirty_raw_nodes,
|
||||
&mut clean_work_products, &mut dirty_work_products, &mut extra_edges);
|
||||
}
|
||||
|
||||
// Add in work-products that are still clean, and delete those that are
|
||||
// dirty.
|
||||
reconcile_work_products(tcx, work_products, &clean_work_products);
|
||||
|
|
@ -393,3 +379,66 @@ fn load_prev_metadata_hashes(tcx: TyCtxt,
|
|||
serialized_hashes.index_map.len());
|
||||
}
|
||||
|
||||
fn process_edges<'a, 'tcx, 'edges>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
source: &'edges DepNode<DefPathIndex>,
|
||||
target: &'edges DepNode<DefPathIndex>,
|
||||
edges: &'edges FxHashMap<DepNode<DefPathIndex>, Vec<DepNode<DefPathIndex>>>,
|
||||
directory: &DefIdDirectory,
|
||||
retraced: &RetracedDefIdDirectory,
|
||||
dirty_raw_nodes: &DirtyNodes,
|
||||
clean_work_products: &mut FxHashSet<Arc<WorkProductId>>,
|
||||
dirty_work_products: &mut FxHashSet<Arc<WorkProductId>>,
|
||||
extra_edges: &mut Vec<(&'edges DepNode<DefPathIndex>, &'edges DepNode<DefPathIndex>)>)
|
||||
{
|
||||
// If the target is dirty, skip the edge. If this is an edge
|
||||
// that targets a work-product, we can print the blame
|
||||
// information now.
|
||||
if let Some(blame) = dirty_raw_nodes.get(target) {
|
||||
if let DepNode::WorkProduct(ref wp) = *target {
|
||||
if tcx.sess.opts.debugging_opts.incremental_info {
|
||||
if dirty_work_products.insert(wp.clone()) {
|
||||
// It'd be nice to pretty-print these paths better than just
|
||||
// using the `Debug` impls, but wev.
|
||||
println!("incremental: module {:?} is dirty because {:?} \
|
||||
changed or was removed",
|
||||
wp,
|
||||
blame.map_def(|&index| {
|
||||
Some(directory.def_path_string(tcx, index))
|
||||
}).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If the source is dirty, the target will be dirty.
|
||||
assert!(!dirty_raw_nodes.contains_key(source));
|
||||
|
||||
// Retrace the source -> target edges to def-ids and then create
|
||||
// an edge in the graph. Retracing may yield none if some of the
|
||||
// data happens to have been removed.
|
||||
if let Some(source_node) = retraced.map(source) {
|
||||
if let Some(target_node) = retraced.map(target) {
|
||||
let _task = tcx.dep_graph.in_task(target_node);
|
||||
tcx.dep_graph.read(source_node);
|
||||
if let DepNode::WorkProduct(ref wp) = *target {
|
||||
clean_work_products.insert(wp.clone());
|
||||
}
|
||||
} else {
|
||||
// As discussed in `decode_dep_graph` above, sometimes the
|
||||
// target cannot be recreated again, in which case we add
|
||||
// edges to go from `source` to the targets of `target`.
|
||||
extra_edges.extend(
|
||||
edges[target].iter().map(|t| (source, t)));
|
||||
}
|
||||
} else {
|
||||
// It's also possible that the source can't be created! But we
|
||||
// can ignore such cases, because (a) if `source` is a HIR
|
||||
// node, it would be considered dirty; and (b) in other cases,
|
||||
// there must be some input to this node that is clean, and so
|
||||
// we'll re-create the edges over in the case where target is
|
||||
// undefined.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -339,6 +339,7 @@ struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
|
|||
|
||||
enum FfiResult {
|
||||
FfiSafe,
|
||||
FfiPhantom,
|
||||
FfiUnsafe(&'static str),
|
||||
FfiBadStruct(DefId, &'static str),
|
||||
FfiBadUnion(DefId, &'static str),
|
||||
|
|
@ -383,8 +384,11 @@ fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
/// Check if the given type is "ffi-safe" (has a stable, well-defined
|
||||
/// representation which can be exported to C code).
|
||||
fn check_type_for_ffi(&self, cache: &mut FxHashSet<Ty<'tcx>>, ty: Ty<'tcx>) -> FfiResult {
|
||||
fn check_type_for_ffi(&self,
|
||||
cache: &mut FxHashSet<Ty<'tcx>>,
|
||||
ty: Ty<'tcx>) -> FfiResult {
|
||||
use self::FfiResult::*;
|
||||
|
||||
let cx = self.cx.tcx;
|
||||
|
||||
// Protect against infinite recursion, for example
|
||||
|
|
@ -397,6 +401,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
|
||||
match ty.sty {
|
||||
ty::TyAdt(def, substs) => {
|
||||
if def.is_phantom_data() {
|
||||
return FfiPhantom;
|
||||
}
|
||||
match def.adt_kind() {
|
||||
AdtKind::Struct => {
|
||||
if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
|
||||
|
|
@ -405,18 +412,22 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
consider adding a #[repr(C)] attribute to the type");
|
||||
}
|
||||
|
||||
// We can't completely trust repr(C) markings; make sure the
|
||||
// fields are actually safe.
|
||||
if def.struct_variant().fields.is_empty() {
|
||||
return FfiUnsafe("found zero-size struct in foreign module, consider \
|
||||
adding a member to this struct");
|
||||
}
|
||||
|
||||
// We can't completely trust repr(C) markings; make sure the
|
||||
// fields are actually safe.
|
||||
let mut all_phantom = true;
|
||||
for field in &def.struct_variant().fields {
|
||||
let field_ty = cx.normalize_associated_type(&field.ty(cx, substs));
|
||||
let r = self.check_type_for_ffi(cache, field_ty);
|
||||
match r {
|
||||
FfiSafe => {}
|
||||
FfiSafe => {
|
||||
all_phantom = false;
|
||||
}
|
||||
FfiPhantom => {}
|
||||
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => {
|
||||
return r;
|
||||
}
|
||||
|
|
@ -425,7 +436,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
FfiSafe
|
||||
|
||||
if all_phantom { FfiPhantom } else { FfiSafe }
|
||||
}
|
||||
AdtKind::Union => {
|
||||
if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
|
||||
|
|
@ -434,11 +446,20 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
consider adding a #[repr(C)] attribute to the type");
|
||||
}
|
||||
|
||||
if def.struct_variant().fields.is_empty() {
|
||||
return FfiUnsafe("found zero-size union in foreign module, consider \
|
||||
adding a member to this union");
|
||||
}
|
||||
|
||||
let mut all_phantom = true;
|
||||
for field in &def.struct_variant().fields {
|
||||
let field_ty = cx.normalize_associated_type(&field.ty(cx, substs));
|
||||
let r = self.check_type_for_ffi(cache, field_ty);
|
||||
match r {
|
||||
FfiSafe => {}
|
||||
FfiSafe => {
|
||||
all_phantom = false;
|
||||
}
|
||||
FfiPhantom => {}
|
||||
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => {
|
||||
return r;
|
||||
}
|
||||
|
|
@ -447,7 +468,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
FfiSafe
|
||||
|
||||
if all_phantom { FfiPhantom } else { FfiSafe }
|
||||
}
|
||||
AdtKind::Enum => {
|
||||
if def.variants.is_empty() {
|
||||
|
|
@ -498,6 +520,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => {
|
||||
return r;
|
||||
}
|
||||
FfiPhantom => {
|
||||
return FfiBadEnum(def.did,
|
||||
"Found phantom data in enum variant");
|
||||
}
|
||||
FfiUnsafe(s) => {
|
||||
return FfiBadEnum(def.did, s);
|
||||
}
|
||||
|
|
@ -591,6 +617,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
|
||||
match self.check_type_for_ffi(&mut FxHashSet(), ty) {
|
||||
FfiResult::FfiSafe => {}
|
||||
FfiResult::FfiPhantom => {
|
||||
self.cx.span_lint(IMPROPER_CTYPES,
|
||||
sp,
|
||||
&format!("found zero-sized type composed only \
|
||||
of phantom-data in a foreign-function."));
|
||||
}
|
||||
FfiResult::FfiUnsafe(s) => {
|
||||
self.cx.span_lint(IMPROPER_CTYPES, sp, s);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,8 +47,6 @@ fn detect_llvm_link(llvm_config: &Path) -> (&'static str, Option<&'static str>)
|
|||
}
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rustc-cfg=cargobuild");
|
||||
|
||||
let target = env::var("TARGET").expect("TARGET was not set");
|
||||
let llvm_config = env::var_os("LLVM_CONFIG")
|
||||
.map(PathBuf::from)
|
||||
|
|
|
|||
|
|
@ -126,6 +126,9 @@ pub enum Attribute {
|
|||
UWTable = 17,
|
||||
ZExt = 18,
|
||||
InReg = 19,
|
||||
SanitizeThread = 20,
|
||||
SanitizeAddress = 21,
|
||||
SanitizeMemory = 22,
|
||||
}
|
||||
|
||||
/// LLVMIntPredicate
|
||||
|
|
@ -1369,14 +1372,14 @@ extern "C" {
|
|||
pub fn LLVMRustDIBuilderCreateBasicType(Builder: DIBuilderRef,
|
||||
Name: *const c_char,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u64,
|
||||
AlignInBits: u32,
|
||||
Encoding: c_uint)
|
||||
-> DIBasicType;
|
||||
|
||||
pub fn LLVMRustDIBuilderCreatePointerType(Builder: DIBuilderRef,
|
||||
PointeeTy: DIType,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u64,
|
||||
AlignInBits: u32,
|
||||
Name: *const c_char)
|
||||
-> DIDerivedType;
|
||||
|
||||
|
|
@ -1386,7 +1389,7 @@ extern "C" {
|
|||
File: DIFile,
|
||||
LineNumber: c_uint,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u64,
|
||||
AlignInBits: u32,
|
||||
Flags: DIFlags,
|
||||
DerivedFrom: DIType,
|
||||
Elements: DIArray,
|
||||
|
|
@ -1401,7 +1404,7 @@ extern "C" {
|
|||
File: DIFile,
|
||||
LineNo: c_uint,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u64,
|
||||
AlignInBits: u32,
|
||||
OffsetInBits: u64,
|
||||
Flags: DIFlags,
|
||||
Ty: DIType)
|
||||
|
|
@ -1429,7 +1432,7 @@ extern "C" {
|
|||
isLocalToUnit: bool,
|
||||
Val: ValueRef,
|
||||
Decl: DIDescriptor,
|
||||
AlignInBits: u64)
|
||||
AlignInBits: u32)
|
||||
-> DIGlobalVariable;
|
||||
|
||||
pub fn LLVMRustDIBuilderCreateVariable(Builder: DIBuilderRef,
|
||||
|
|
@ -1442,19 +1445,19 @@ extern "C" {
|
|||
AlwaysPreserve: bool,
|
||||
Flags: DIFlags,
|
||||
ArgNo: c_uint,
|
||||
AlignInBits: u64)
|
||||
AlignInBits: u32)
|
||||
-> DIVariable;
|
||||
|
||||
pub fn LLVMRustDIBuilderCreateArrayType(Builder: DIBuilderRef,
|
||||
Size: u64,
|
||||
AlignInBits: u64,
|
||||
AlignInBits: u32,
|
||||
Ty: DIType,
|
||||
Subscripts: DIArray)
|
||||
-> DIType;
|
||||
|
||||
pub fn LLVMRustDIBuilderCreateVectorType(Builder: DIBuilderRef,
|
||||
Size: u64,
|
||||
AlignInBits: u64,
|
||||
AlignInBits: u32,
|
||||
Ty: DIType,
|
||||
Subscripts: DIArray)
|
||||
-> DIType;
|
||||
|
|
@ -1489,7 +1492,7 @@ extern "C" {
|
|||
File: DIFile,
|
||||
LineNumber: c_uint,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u64,
|
||||
AlignInBits: u32,
|
||||
Elements: DIArray,
|
||||
ClassType: DIType)
|
||||
-> DIType;
|
||||
|
|
@ -1500,7 +1503,7 @@ extern "C" {
|
|||
File: DIFile,
|
||||
LineNumber: c_uint,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u64,
|
||||
AlignInBits: u32,
|
||||
Flags: DIFlags,
|
||||
Elements: DIArray,
|
||||
RunTimeLang: c_uint,
|
||||
|
|
|
|||
|
|
@ -422,13 +422,3 @@ impl Drop for OperandBundleDef {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The module containing the native LLVM dependencies, generated by the build system
|
||||
// Note that this must come after the rustllvm extern declaration so that
|
||||
// parts of LLVM that rustllvm depends on aren't thrown away by the linker.
|
||||
// Works to the above fix for #15460 to ensure LLVM dependencies that
|
||||
// are only used by rustllvm don't get stripped by the linker.
|
||||
#[cfg(not(cargobuild))]
|
||||
mod llvmdeps {
|
||||
include! { env!("CFG_LLVM_LINKAGE_FILE") }
|
||||
}
|
||||
|
|
|
|||
17
src/librustc_lsan/Cargo.toml
Normal file
17
src/librustc_lsan/Cargo.toml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
[package]
|
||||
authors = ["The Rust Project Developers"]
|
||||
build = "build.rs"
|
||||
name = "rustc_lsan"
|
||||
version = "0.0.0"
|
||||
|
||||
[lib]
|
||||
name = "rustc_lsan"
|
||||
path = "lib.rs"
|
||||
|
||||
[build-dependencies]
|
||||
build_helper = { path = "../build_helper" }
|
||||
cmake = "0.1.18"
|
||||
|
||||
[dependencies]
|
||||
alloc_system = { path = "../liballoc_system" }
|
||||
core = { path = "../libcore" }
|
||||
39
src/librustc_lsan/build.rs
Normal file
39
src/librustc_lsan/build.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// 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.
|
||||
|
||||
extern crate build_helper;
|
||||
extern crate cmake;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::env;
|
||||
|
||||
use cmake::Config;
|
||||
|
||||
fn main() {
|
||||
if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
|
||||
let dst = Config::new("../compiler-rt")
|
||||
.define("COMPILER_RT_BUILD_SANITIZERS", "ON")
|
||||
.define("COMPILER_RT_BUILD_BUILTINS", "OFF")
|
||||
.define("COMPILER_RT_BUILD_XRAY", "OFF")
|
||||
.define("LLVM_CONFIG_PATH", llvm_config)
|
||||
.build_target("lsan")
|
||||
.build();
|
||||
|
||||
println!("cargo:rustc-link-search=native={}",
|
||||
dst.join("build/lib/linux").display());
|
||||
println!("cargo:rustc-link-lib=static=clang_rt.lsan-x86_64");
|
||||
|
||||
build_helper::rerun_if_changed_anything_in_dir(&PathBuf::from(env::var("CARGO_MANIFEST_DIR")
|
||||
.unwrap())
|
||||
.join("../compiler-rt"));
|
||||
}
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
}
|
||||
20
src/librustc_lsan/lib.rs
Normal file
20
src/librustc_lsan/lib.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// 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.
|
||||
|
||||
#![cfg_attr(not(stage0), feature(sanitizer_runtime))]
|
||||
#![cfg_attr(not(stage0), sanitizer_runtime)]
|
||||
#![feature(alloc_system)]
|
||||
#![feature(staged_api)]
|
||||
#![no_std]
|
||||
#![unstable(feature = "sanitizer_runtime_lib",
|
||||
reason = "internal implementation detail of sanitizers",
|
||||
issue = "0")]
|
||||
|
||||
extern crate alloc_system;
|
||||
|
|
@ -17,7 +17,8 @@ use schema::CrateRoot;
|
|||
use rustc::hir::def_id::{CrateNum, DefIndex};
|
||||
use rustc::hir::svh::Svh;
|
||||
use rustc::middle::cstore::DepKind;
|
||||
use rustc::session::{config, Session};
|
||||
use rustc::session::Session;
|
||||
use rustc::session::config::{Sanitizer, self};
|
||||
use rustc_back::PanicStrategy;
|
||||
use rustc::session::search_paths::PathKind;
|
||||
use rustc::middle;
|
||||
|
|
@ -786,6 +787,64 @@ impl<'a> CrateLoader<'a> {
|
|||
&|data| data.needs_panic_runtime());
|
||||
}
|
||||
|
||||
fn inject_sanitizer_runtime(&mut self) {
|
||||
if let Some(ref sanitizer) = self.sess.opts.debugging_opts.sanitizer {
|
||||
// Sanitizers can only be used with x86_64 Linux executables linked
|
||||
// to `std`
|
||||
if self.sess.target.target.llvm_target != "x86_64-unknown-linux-gnu" {
|
||||
self.sess.err(&format!("Sanitizers only work with the \
|
||||
`x86_64-unknown-linux-gnu` target."));
|
||||
return
|
||||
}
|
||||
|
||||
if !self.sess.crate_types.borrow().iter().all(|ct| {
|
||||
match *ct {
|
||||
// Link the runtime
|
||||
config::CrateTypeExecutable => true,
|
||||
// This crate will be compiled with the required
|
||||
// instrumentation pass
|
||||
config::CrateTypeRlib => false,
|
||||
_ => {
|
||||
self.sess.err(&format!("Only executables and rlibs can be \
|
||||
compiled with `-Z sanitizer`"));
|
||||
false
|
||||
}
|
||||
}
|
||||
}) {
|
||||
return
|
||||
}
|
||||
|
||||
let mut uses_std = false;
|
||||
self.cstore.iter_crate_data(|_, data| {
|
||||
if data.name == "std" {
|
||||
uses_std = true;
|
||||
}
|
||||
});
|
||||
|
||||
if uses_std {
|
||||
let name = match *sanitizer {
|
||||
Sanitizer::Address => "rustc_asan",
|
||||
Sanitizer::Leak => "rustc_lsan",
|
||||
Sanitizer::Memory => "rustc_msan",
|
||||
Sanitizer::Thread => "rustc_tsan",
|
||||
};
|
||||
info!("loading sanitizer: {}", name);
|
||||
|
||||
let symbol = Symbol::intern(name);
|
||||
let dep_kind = DepKind::Implicit;
|
||||
let (_, data) =
|
||||
self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP,
|
||||
PathKind::Crate, dep_kind);
|
||||
|
||||
// Sanity check the loaded crate to ensure it is indeed a sanitizer runtime
|
||||
if !data.is_sanitizer_runtime() {
|
||||
self.sess.err(&format!("the crate `{}` is not a sanitizer runtime",
|
||||
name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn inject_allocator_crate(&mut self) {
|
||||
// Make sure that we actually need an allocator, if none of our
|
||||
// dependencies need one then we definitely don't!
|
||||
|
|
@ -982,6 +1041,9 @@ impl<'a> CrateLoader<'a> {
|
|||
|
||||
impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
|
||||
fn postprocess(&mut self, krate: &ast::Crate) {
|
||||
// inject the sanitizer runtime before the allocator runtime because all
|
||||
// sanitizers force the use of the `alloc_system` allocator
|
||||
self.inject_sanitizer_runtime();
|
||||
self.inject_allocator_crate();
|
||||
self.inject_panic_runtime(krate);
|
||||
|
||||
|
|
|
|||
|
|
@ -297,6 +297,11 @@ impl CrateMetadata {
|
|||
attr::contains_name(&attrs, "compiler_builtins")
|
||||
}
|
||||
|
||||
pub fn is_sanitizer_runtime(&self) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
|
||||
attr::contains_name(&attrs, "sanitizer_runtime")
|
||||
}
|
||||
|
||||
pub fn is_no_builtins(&self) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
|
||||
attr::contains_name(&attrs, "no_builtins")
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue