Format the world
This commit is contained in:
parent
8eb7c58dbb
commit
a06baa56b9
|
@ -2,8 +2,8 @@
|
|||
// `src/bootstrap/native.rs` for why this is needed when compiling LLD.
|
||||
|
||||
use std::env;
|
||||
use std::process::{self, Stdio, Command};
|
||||
use std::io::{self, Write};
|
||||
use std::process::{self, Command, Stdio};
|
||||
|
||||
fn main() {
|
||||
let real_llvm_config = env::var_os("LLVM_CONFIG_REAL").unwrap();
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
use std::env;
|
||||
|
||||
use bootstrap::{Config, Build};
|
||||
use bootstrap::{Build, Config};
|
||||
|
||||
fn main() {
|
||||
let args = env::args().skip(1).collect::<Vec<_>>();
|
||||
|
|
|
@ -27,9 +27,7 @@ fn main() {
|
|||
|
||||
// Detect whether or not we're a build script depending on whether --target
|
||||
// is passed (a bit janky...)
|
||||
let target = args.windows(2)
|
||||
.find(|w| &*w[0] == "--target")
|
||||
.and_then(|w| w[1].to_str());
|
||||
let target = args.windows(2).find(|w| &*w[0] == "--target").and_then(|w| w[1].to_str());
|
||||
let version = args.iter().find(|w| &**w == "-vV");
|
||||
|
||||
let verbose = match env::var("RUSTC_VERBOSE") {
|
||||
|
@ -57,19 +55,16 @@ fn main() {
|
|||
dylib_path.insert(0, PathBuf::from(&libdir));
|
||||
|
||||
let mut cmd = Command::new(rustc);
|
||||
cmd.args(&args)
|
||||
.env(bootstrap::util::dylib_path_var(),
|
||||
env::join_paths(&dylib_path).unwrap());
|
||||
cmd.args(&args).env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap());
|
||||
|
||||
// Get the name of the crate we're compiling, if any.
|
||||
let crate_name = args.windows(2)
|
||||
.find(|args| args[0] == "--crate-name")
|
||||
.and_then(|args| args[1].to_str());
|
||||
let crate_name =
|
||||
args.windows(2).find(|args| args[0] == "--crate-name").and_then(|args| args[1].to_str());
|
||||
|
||||
if let Some(crate_name) = crate_name {
|
||||
if let Some(target) = env::var_os("RUSTC_TIME") {
|
||||
if target == "all" ||
|
||||
target.into_string().unwrap().split(",").any(|c| c.trim() == crate_name)
|
||||
if target == "all"
|
||||
|| target.into_string().unwrap().split(",").any(|c| c.trim() == crate_name)
|
||||
{
|
||||
cmd.arg("-Ztime");
|
||||
}
|
||||
|
@ -101,15 +96,22 @@ fn main() {
|
|||
// `compiler_builtins` are unconditionally compiled with panic=abort to
|
||||
// workaround undefined references to `rust_eh_unwind_resume` generated
|
||||
// otherwise, see issue https://github.com/rust-lang/rust/issues/43095.
|
||||
if crate_name == Some("panic_abort") ||
|
||||
crate_name == Some("compiler_builtins") && stage != "0" {
|
||||
if crate_name == Some("panic_abort")
|
||||
|| crate_name == Some("compiler_builtins") && stage != "0"
|
||||
{
|
||||
cmd.arg("-C").arg("panic=abort");
|
||||
}
|
||||
|
||||
// Set various options from config.toml to configure how we're building
|
||||
// code.
|
||||
let debug_assertions = match env::var("RUSTC_DEBUG_ASSERTIONS") {
|
||||
Ok(s) => if s == "true" { "y" } else { "n" },
|
||||
Ok(s) => {
|
||||
if s == "true" {
|
||||
"y"
|
||||
} else {
|
||||
"n"
|
||||
}
|
||||
}
|
||||
Err(..) => "n",
|
||||
};
|
||||
|
||||
|
@ -178,17 +180,17 @@ fn main() {
|
|||
if env::var_os("RUSTC_PRINT_STEP_TIMINGS").is_some() {
|
||||
if let Some(crate_name) = crate_name {
|
||||
let start = Instant::now();
|
||||
let status = cmd
|
||||
.status()
|
||||
.unwrap_or_else(|_| panic!("\n\n failed to run {:?}", cmd));
|
||||
let status = cmd.status().unwrap_or_else(|_| panic!("\n\n failed to run {:?}", cmd));
|
||||
let dur = start.elapsed();
|
||||
|
||||
let is_test = args.iter().any(|a| a == "--test");
|
||||
eprintln!("[RUSTC-TIMING] {} test:{} {}.{:03}",
|
||||
crate_name,
|
||||
is_test,
|
||||
dur.as_secs(),
|
||||
dur.subsec_nanos() / 1_000_000);
|
||||
eprintln!(
|
||||
"[RUSTC-TIMING] {} test:{} {}.{:03}",
|
||||
crate_name,
|
||||
is_test,
|
||||
dur.as_secs(),
|
||||
dur.subsec_nanos() / 1_000_000
|
||||
);
|
||||
|
||||
match status.code() {
|
||||
Some(i) => std::process::exit(i),
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
//! See comments in `src/bootstrap/rustc.rs` for more information.
|
||||
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
use std::path::PathBuf;
|
||||
use std::ffi::OsString;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
fn main() {
|
||||
let args = env::args_os().skip(1).collect::<Vec<_>>();
|
||||
|
@ -35,8 +35,7 @@ fn main() {
|
|||
.arg("dox")
|
||||
.arg("--sysroot")
|
||||
.arg(&sysroot)
|
||||
.env(bootstrap::util::dylib_path_var(),
|
||||
env::join_paths(&dylib_path).unwrap());
|
||||
.env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap());
|
||||
|
||||
// Force all crates compiled by this compiler to (a) be unstable and (b)
|
||||
// allow the `rustc_private` feature to link to other unstable crates
|
||||
|
@ -55,8 +54,7 @@ fn main() {
|
|||
if let Some(version) = env::var_os("RUSTDOC_CRATE_VERSION") {
|
||||
// This "unstable-options" can be removed when `--crate-version` is stabilized
|
||||
if !has_unstable {
|
||||
cmd.arg("-Z")
|
||||
.arg("unstable-options");
|
||||
cmd.arg("-Z").arg("unstable-options");
|
||||
}
|
||||
cmd.arg("--crate-version").arg(version);
|
||||
has_unstable = true;
|
||||
|
@ -66,8 +64,7 @@ fn main() {
|
|||
if let Some(_) = env::var_os("RUSTDOC_GENERATE_REDIRECT_PAGES") {
|
||||
// This "unstable-options" can be removed when `--generate-redirect-pages` is stabilized
|
||||
if !has_unstable {
|
||||
cmd.arg("-Z")
|
||||
.arg("unstable-options");
|
||||
cmd.arg("-Z").arg("unstable-options");
|
||||
}
|
||||
cmd.arg("--generate-redirect-pages");
|
||||
has_unstable = true;
|
||||
|
@ -77,8 +74,7 @@ fn main() {
|
|||
if let Some(ref x) = env::var_os("RUSTDOC_RESOURCE_SUFFIX") {
|
||||
// This "unstable-options" can be removed when `--resource-suffix` is stabilized
|
||||
if !has_unstable {
|
||||
cmd.arg("-Z")
|
||||
.arg("unstable-options");
|
||||
cmd.arg("-Z").arg("unstable-options");
|
||||
}
|
||||
cmd.arg("--resource-suffix").arg(x);
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ fn main() {
|
|||
env::set_var("CXX", env::var_os("SCCACHE_CXX").unwrap());
|
||||
let mut cfg = cc::Build::new();
|
||||
cfg.cargo_metadata(false)
|
||||
.out_dir("/")
|
||||
.target(&target)
|
||||
.host(&target)
|
||||
.opt_level(0)
|
||||
.warnings(false)
|
||||
.debug(false);
|
||||
.out_dir("/")
|
||||
.target(&target)
|
||||
.host(&target)
|
||||
.opt_level(0)
|
||||
.warnings(false)
|
||||
.debug(false);
|
||||
let compiler = cfg.get_compiler();
|
||||
|
||||
// Invoke sccache with said compiler
|
||||
|
|
|
@ -24,7 +24,7 @@ use crate::native;
|
|||
use crate::test;
|
||||
use crate::tool;
|
||||
use crate::util::{self, add_lib_path, exe, libdir};
|
||||
use crate::{Build, DocTests, Mode, GitRepo};
|
||||
use crate::{Build, DocTests, GitRepo, Mode};
|
||||
|
||||
pub use crate::Compiler;
|
||||
|
||||
|
@ -122,11 +122,7 @@ impl PathSet {
|
|||
|
||||
fn path(&self, builder: &Builder<'_>) -> PathBuf {
|
||||
match self {
|
||||
PathSet::Set(set) => set
|
||||
.iter()
|
||||
.next()
|
||||
.unwrap_or(&builder.build.src)
|
||||
.to_path_buf(),
|
||||
PathSet::Set(set) => set.iter().next().unwrap_or(&builder.build.src).to_path_buf(),
|
||||
PathSet::Suite(path) => PathBuf::from(path),
|
||||
}
|
||||
}
|
||||
|
@ -180,10 +176,8 @@ impl StepDescription {
|
|||
}
|
||||
|
||||
fn run(v: &[StepDescription], builder: &Builder<'_>, paths: &[PathBuf]) {
|
||||
let should_runs = v
|
||||
.iter()
|
||||
.map(|desc| (desc.should_run)(ShouldRun::new(builder)))
|
||||
.collect::<Vec<_>>();
|
||||
let should_runs =
|
||||
v.iter().map(|desc| (desc.should_run)(ShouldRun::new(builder))).collect::<Vec<_>>();
|
||||
|
||||
// sanity checks on rules
|
||||
for (desc, should_run) in v.iter().zip(&should_runs) {
|
||||
|
@ -280,8 +274,7 @@ impl<'a> ShouldRun<'a> {
|
|||
|
||||
// multiple aliases for the same job
|
||||
pub fn paths(mut self, paths: &[&str]) -> Self {
|
||||
self.paths
|
||||
.insert(PathSet::Set(paths.iter().map(PathBuf::from).collect()));
|
||||
self.paths.insert(PathSet::Set(paths.iter().map(PathBuf::from).collect()));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -354,11 +347,9 @@ impl<'a> Builder<'a> {
|
|||
tool::Miri,
|
||||
native::Lld
|
||||
),
|
||||
Kind::Check | Kind::Clippy | Kind::Fix | Kind::Format => describe!(
|
||||
check::Std,
|
||||
check::Rustc,
|
||||
check::Rustdoc
|
||||
),
|
||||
Kind::Check | Kind::Clippy | Kind::Fix | Kind::Format => {
|
||||
describe!(check::Std, check::Rustc, check::Rustdoc)
|
||||
}
|
||||
Kind::Test => describe!(
|
||||
crate::toolstate::ToolStateCheck,
|
||||
test::Tidy,
|
||||
|
@ -549,9 +540,7 @@ impl<'a> Builder<'a> {
|
|||
/// obtained through this function, since it ensures that they are valid
|
||||
/// (i.e., built and assembled).
|
||||
pub fn compiler(&self, stage: u32, host: Interned<String>) -> Compiler {
|
||||
self.ensure(compile::Assemble {
|
||||
target_compiler: Compiler { stage, host },
|
||||
})
|
||||
self.ensure(compile::Assemble { target_compiler: Compiler { stage, host } })
|
||||
}
|
||||
|
||||
/// Similar to `compiler`, except handles the full-bootstrap option to
|
||||
|
@ -627,9 +616,10 @@ impl<'a> Builder<'a> {
|
|||
self.rustc_snapshot_libdir()
|
||||
} else {
|
||||
match self.config.libdir_relative() {
|
||||
Some(relative_libdir) if compiler.stage >= 1
|
||||
=> self.sysroot(compiler).join(relative_libdir),
|
||||
_ => self.sysroot(compiler).join(libdir(&compiler.host))
|
||||
Some(relative_libdir) if compiler.stage >= 1 => {
|
||||
self.sysroot(compiler).join(relative_libdir)
|
||||
}
|
||||
_ => self.sysroot(compiler).join(libdir(&compiler.host)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -644,9 +634,8 @@ impl<'a> Builder<'a> {
|
|||
libdir(&self.config.build).as_ref()
|
||||
} else {
|
||||
match self.config.libdir_relative() {
|
||||
Some(relative_libdir) if compiler.stage >= 1
|
||||
=> relative_libdir,
|
||||
_ => libdir(&compiler.host).as_ref()
|
||||
Some(relative_libdir) if compiler.stage >= 1 => relative_libdir,
|
||||
_ => libdir(&compiler.host).as_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -657,9 +646,8 @@ impl<'a> Builder<'a> {
|
|||
/// For example this returns `lib` on Unix and Windows.
|
||||
pub fn sysroot_libdir_relative(&self, compiler: Compiler) -> &Path {
|
||||
match self.config.libdir_relative() {
|
||||
Some(relative_libdir) if compiler.stage >= 1
|
||||
=> relative_libdir,
|
||||
_ => Path::new("lib")
|
||||
Some(relative_libdir) if compiler.stage >= 1 => relative_libdir,
|
||||
_ => Path::new("lib"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -681,9 +669,7 @@ impl<'a> Builder<'a> {
|
|||
if compiler.is_snapshot(self) {
|
||||
self.initial_rustc.clone()
|
||||
} else {
|
||||
self.sysroot(compiler)
|
||||
.join("bin")
|
||||
.join(exe("rustc", &compiler.host))
|
||||
self.sysroot(compiler).join("bin").join(exe("rustc", &compiler.host))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -740,17 +726,10 @@ impl<'a> Builder<'a> {
|
|||
self.clear_if_dirty(&my_out, &rustdoc);
|
||||
}
|
||||
|
||||
cargo
|
||||
.env("CARGO_TARGET_DIR", out_dir)
|
||||
.arg(cmd)
|
||||
.arg("-Zconfig-profile");
|
||||
cargo.env("CARGO_TARGET_DIR", out_dir).arg(cmd).arg("-Zconfig-profile");
|
||||
|
||||
let profile_var = |name: &str| {
|
||||
let profile = if self.config.rust_optimize {
|
||||
"RELEASE"
|
||||
} else {
|
||||
"DEV"
|
||||
};
|
||||
let profile = if self.config.rust_optimize { "RELEASE" } else { "DEV" };
|
||||
format!("CARGO_PROFILE_{}_{}", profile, name)
|
||||
};
|
||||
|
||||
|
@ -762,8 +741,7 @@ impl<'a> Builder<'a> {
|
|||
}
|
||||
|
||||
if cmd != "install" {
|
||||
cargo.arg("--target")
|
||||
.arg(target);
|
||||
cargo.arg("--target").arg(target);
|
||||
} else {
|
||||
assert_eq!(target, compiler.host);
|
||||
}
|
||||
|
@ -801,14 +779,14 @@ impl<'a> Builder<'a> {
|
|||
}
|
||||
|
||||
match mode {
|
||||
Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {},
|
||||
Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {}
|
||||
Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {
|
||||
// Build proc macros both for the host and the target
|
||||
if target != compiler.host && cmd != "check" {
|
||||
cargo.arg("-Zdual-proc-macros");
|
||||
rustflags.arg("-Zdual-proc-macros");
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// This tells Cargo (and in turn, rustc) to output more complete
|
||||
|
@ -884,11 +862,7 @@ impl<'a> Builder<'a> {
|
|||
assert!(!use_snapshot || stage == 0 || self.local_rebuild);
|
||||
|
||||
let maybe_sysroot = self.sysroot(compiler);
|
||||
let sysroot = if use_snapshot {
|
||||
self.rustc_snapshot_sysroot()
|
||||
} else {
|
||||
&maybe_sysroot
|
||||
};
|
||||
let sysroot = if use_snapshot { self.rustc_snapshot_sysroot() } else { &maybe_sysroot };
|
||||
let libdir = self.rustc_libdir(compiler);
|
||||
|
||||
// Customize the compiler we're running. Specify the compiler to cargo
|
||||
|
@ -902,10 +876,7 @@ impl<'a> Builder<'a> {
|
|||
.env("RUSTC", self.out.join("bootstrap/debug/rustc"))
|
||||
.env("RUSTC_REAL", self.rustc(compiler))
|
||||
.env("RUSTC_STAGE", stage.to_string())
|
||||
.env(
|
||||
"RUSTC_DEBUG_ASSERTIONS",
|
||||
self.config.rust_debug_assertions.to_string(),
|
||||
)
|
||||
.env("RUSTC_DEBUG_ASSERTIONS", self.config.rust_debug_assertions.to_string())
|
||||
.env("RUSTC_SYSROOT", &sysroot)
|
||||
.env("RUSTC_LIBDIR", &libdir)
|
||||
.env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc"))
|
||||
|
@ -948,7 +919,6 @@ impl<'a> Builder<'a> {
|
|||
// to change a flag in a binary?
|
||||
if self.config.rust_rpath && util::use_host_linker(&target) {
|
||||
let rpath = if target.contains("apple") {
|
||||
|
||||
// Note that we need to take one extra step on macOS to also pass
|
||||
// `-Wl,-instal_name,@rpath/...` to get things to work right. To
|
||||
// do that we pass a weird flag to the compiler to get it to do
|
||||
|
@ -980,8 +950,9 @@ impl<'a> Builder<'a> {
|
|||
let debuginfo_level = match mode {
|
||||
Mode::Rustc | Mode::Codegen => self.config.rust_debuginfo_level_rustc,
|
||||
Mode::Std => self.config.rust_debuginfo_level_std,
|
||||
Mode::ToolBootstrap | Mode::ToolStd |
|
||||
Mode::ToolRustc => self.config.rust_debuginfo_level_tools,
|
||||
Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolRustc => {
|
||||
self.config.rust_debuginfo_level_tools
|
||||
}
|
||||
};
|
||||
cargo.env(profile_var("DEBUG"), debuginfo_level.to_string());
|
||||
|
||||
|
@ -1102,14 +1073,11 @@ impl<'a> Builder<'a> {
|
|||
cargo.env(format!("CC_{}", target), &cc);
|
||||
|
||||
let cflags = self.cflags(target, GitRepo::Rustc).join(" ");
|
||||
cargo
|
||||
.env(format!("CFLAGS_{}", target), cflags.clone());
|
||||
cargo.env(format!("CFLAGS_{}", target), cflags.clone());
|
||||
|
||||
if let Some(ar) = self.ar(target) {
|
||||
let ranlib = format!("{} s", ar.display());
|
||||
cargo
|
||||
.env(format!("AR_{}", target), ar)
|
||||
.env(format!("RANLIB_{}", target), ranlib);
|
||||
cargo.env(format!("AR_{}", target), ar).env(format!("RANLIB_{}", target), ranlib);
|
||||
}
|
||||
|
||||
if let Ok(cxx) = self.cxx(target) {
|
||||
|
@ -1120,15 +1088,14 @@ impl<'a> Builder<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
if mode == Mode::Std
|
||||
&& self.config.extended
|
||||
&& compiler.is_final_stage(self)
|
||||
{
|
||||
if mode == Mode::Std && self.config.extended && compiler.is_final_stage(self) {
|
||||
rustflags.arg("-Zsave-analysis");
|
||||
cargo.env("RUST_SAVE_ANALYSIS_CONFIG",
|
||||
"{\"output_file\": null,\"full_docs\": false,\
|
||||
cargo.env(
|
||||
"RUST_SAVE_ANALYSIS_CONFIG",
|
||||
"{\"output_file\": null,\"full_docs\": false,\
|
||||
\"pub_only\": true,\"reachable_only\": false,\
|
||||
\"distro_crate\": true,\"signatures\": false,\"borrow_data\": false}");
|
||||
\"distro_crate\": true,\"signatures\": false,\"borrow_data\": false}",
|
||||
);
|
||||
}
|
||||
|
||||
// For `cargo doc` invocations, make rustdoc print the Rust version into the docs
|
||||
|
@ -1182,8 +1149,7 @@ impl<'a> Builder<'a> {
|
|||
}
|
||||
|
||||
match (mode, self.config.rust_codegen_units_std, self.config.rust_codegen_units) {
|
||||
(Mode::Std, Some(n), _) |
|
||||
(_, _, Some(n)) => {
|
||||
(Mode::Std, Some(n), _) | (_, _, Some(n)) => {
|
||||
cargo.env(profile_var("CODEGEN_UNITS"), n.to_string());
|
||||
}
|
||||
_ => {
|
||||
|
@ -1217,10 +1183,7 @@ impl<'a> Builder<'a> {
|
|||
rustflags.arg("-Cprefer-dynamic");
|
||||
}
|
||||
|
||||
Cargo {
|
||||
command: cargo,
|
||||
rustflags,
|
||||
}
|
||||
Cargo { command: cargo, rustflags }
|
||||
}
|
||||
|
||||
/// Ensure that a given step is built, returning its output. This will
|
||||
|
@ -1231,10 +1194,7 @@ impl<'a> Builder<'a> {
|
|||
let mut stack = self.stack.borrow_mut();
|
||||
for stack_step in stack.iter() {
|
||||
// should skip
|
||||
if stack_step
|
||||
.downcast_ref::<S>()
|
||||
.map_or(true, |stack_step| *stack_step != step)
|
||||
{
|
||||
if stack_step.downcast_ref::<S>().map_or(true, |stack_step| *stack_step != step) {
|
||||
continue;
|
||||
}
|
||||
let mut out = String::new();
|
||||
|
@ -1277,11 +1237,7 @@ impl<'a> Builder<'a> {
|
|||
let cur_step = stack.pop().expect("step stack empty");
|
||||
assert_eq!(cur_step.downcast_ref(), Some(&step));
|
||||
}
|
||||
self.verbose(&format!(
|
||||
"{}< {:?}",
|
||||
" ".repeat(self.stack.borrow().len()),
|
||||
step
|
||||
));
|
||||
self.verbose(&format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step));
|
||||
self.cache.put(step, out.clone());
|
||||
out
|
||||
}
|
||||
|
@ -1344,7 +1300,9 @@ impl Cargo {
|
|||
}
|
||||
|
||||
pub fn args<I, S>(&mut self, args: I) -> &mut Cargo
|
||||
where I: IntoIterator<Item=S>, S: AsRef<OsStr>
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
for arg in args {
|
||||
self.arg(arg.as_ref());
|
||||
|
|
|
@ -11,12 +11,10 @@ fn configure(host: &[&str], target: &[&str]) -> Config {
|
|||
config.skip_only_host_steps = false;
|
||||
config.dry_run = true;
|
||||
// try to avoid spurious failures in dist where we create/delete each others file
|
||||
let dir = config.out.join("tmp-rustbuild-tests").join(
|
||||
&thread::current()
|
||||
.name()
|
||||
.unwrap_or("unknown")
|
||||
.replace(":", "-"),
|
||||
);
|
||||
let dir = config
|
||||
.out
|
||||
.join("tmp-rustbuild-tests")
|
||||
.join(&thread::current().name().unwrap_or("unknown").replace(":", "-"));
|
||||
t!(fs::create_dir_all(&dir));
|
||||
config.out = dir;
|
||||
config.build = INTERNER.intern_str("A");
|
||||
|
@ -46,26 +44,15 @@ fn dist_baseline() {
|
|||
|
||||
let a = INTERNER.intern_str("A");
|
||||
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Docs>()),
|
||||
&[dist::Docs { host: a },]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Mingw>()),
|
||||
&[dist::Mingw { host: a },]
|
||||
);
|
||||
assert_eq!(first(builder.cache.all::<dist::Docs>()), &[dist::Docs { host: a },]);
|
||||
assert_eq!(first(builder.cache.all::<dist::Mingw>()), &[dist::Mingw { host: a },]);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Rustc>()),
|
||||
&[dist::Rustc {
|
||||
compiler: Compiler { host: a, stage: 2 }
|
||||
},]
|
||||
&[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Std>()),
|
||||
&[dist::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: a,
|
||||
},]
|
||||
&[dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },]
|
||||
);
|
||||
assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
|
||||
}
|
||||
|
@ -81,10 +68,7 @@ fn dist_with_targets() {
|
|||
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Docs>()),
|
||||
&[
|
||||
dist::Docs { host: a },
|
||||
dist::Docs { host: b },
|
||||
]
|
||||
&[dist::Docs { host: a }, dist::Docs { host: b },]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Mingw>()),
|
||||
|
@ -92,21 +76,13 @@ fn dist_with_targets() {
|
|||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Rustc>()),
|
||||
&[dist::Rustc {
|
||||
compiler: Compiler { host: a, stage: 2 }
|
||||
},]
|
||||
&[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Std>()),
|
||||
&[
|
||||
dist::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: a,
|
||||
},
|
||||
dist::Std {
|
||||
compiler: Compiler { host: a, stage: 2 },
|
||||
target: b,
|
||||
},
|
||||
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
|
||||
dist::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
|
||||
]
|
||||
);
|
||||
assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
|
||||
|
@ -123,10 +99,7 @@ fn dist_with_hosts() {
|
|||
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Docs>()),
|
||||
&[
|
||||
dist::Docs { host: a },
|
||||
dist::Docs { host: b },
|
||||
]
|
||||
&[dist::Docs { host: a }, dist::Docs { host: b },]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Mingw>()),
|
||||
|
@ -135,25 +108,15 @@ fn dist_with_hosts() {
|
|||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Rustc>()),
|
||||
&[
|
||||
dist::Rustc {
|
||||
compiler: Compiler { host: a, stage: 2 }
|
||||
},
|
||||
dist::Rustc {
|
||||
compiler: Compiler { host: b, stage: 2 }
|
||||
},
|
||||
dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
|
||||
dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Std>()),
|
||||
&[
|
||||
dist::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: a,
|
||||
},
|
||||
dist::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: b,
|
||||
},
|
||||
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
|
||||
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
]
|
||||
);
|
||||
assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
|
||||
|
@ -172,23 +135,13 @@ fn dist_only_cross_host() {
|
|||
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Rustc>()),
|
||||
&[
|
||||
dist::Rustc {
|
||||
compiler: Compiler { host: b, stage: 2 }
|
||||
},
|
||||
]
|
||||
&[dist::Rustc { compiler: Compiler { host: b, stage: 2 } },]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<compile::Rustc>()),
|
||||
&[
|
||||
compile::Rustc {
|
||||
compiler: Compiler { host: a, stage: 0 },
|
||||
target: a,
|
||||
},
|
||||
compile::Rustc {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: b,
|
||||
},
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -205,46 +158,25 @@ fn dist_with_targets_and_hosts() {
|
|||
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Docs>()),
|
||||
&[
|
||||
dist::Docs { host: a },
|
||||
dist::Docs { host: b },
|
||||
dist::Docs { host: c },
|
||||
]
|
||||
&[dist::Docs { host: a }, dist::Docs { host: b }, dist::Docs { host: c },]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Mingw>()),
|
||||
&[
|
||||
dist::Mingw { host: a },
|
||||
dist::Mingw { host: b },
|
||||
dist::Mingw { host: c },
|
||||
]
|
||||
&[dist::Mingw { host: a }, dist::Mingw { host: b }, dist::Mingw { host: c },]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Rustc>()),
|
||||
&[
|
||||
dist::Rustc {
|
||||
compiler: Compiler { host: a, stage: 2 }
|
||||
},
|
||||
dist::Rustc {
|
||||
compiler: Compiler { host: b, stage: 2 }
|
||||
},
|
||||
dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
|
||||
dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Std>()),
|
||||
&[
|
||||
dist::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: a,
|
||||
},
|
||||
dist::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: b,
|
||||
},
|
||||
dist::Std {
|
||||
compiler: Compiler { host: a, stage: 2 },
|
||||
target: c,
|
||||
},
|
||||
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
|
||||
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
|
||||
]
|
||||
);
|
||||
assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
|
||||
|
@ -264,36 +196,19 @@ fn dist_with_target_flag() {
|
|||
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Docs>()),
|
||||
&[
|
||||
dist::Docs { host: a },
|
||||
dist::Docs { host: b },
|
||||
dist::Docs { host: c },
|
||||
]
|
||||
&[dist::Docs { host: a }, dist::Docs { host: b }, dist::Docs { host: c },]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Mingw>()),
|
||||
&[
|
||||
dist::Mingw { host: a },
|
||||
dist::Mingw { host: b },
|
||||
dist::Mingw { host: c },
|
||||
]
|
||||
&[dist::Mingw { host: a }, dist::Mingw { host: b }, dist::Mingw { host: c },]
|
||||
);
|
||||
assert_eq!(first(builder.cache.all::<dist::Rustc>()), &[]);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Std>()),
|
||||
&[
|
||||
dist::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: a,
|
||||
},
|
||||
dist::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: b,
|
||||
},
|
||||
dist::Std {
|
||||
compiler: Compiler { host: a, stage: 2 },
|
||||
target: c,
|
||||
},
|
||||
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
|
||||
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
|
||||
]
|
||||
);
|
||||
assert_eq!(first(builder.cache.all::<dist::Src>()), &[]);
|
||||
|
@ -310,10 +225,7 @@ fn dist_with_same_targets_and_hosts() {
|
|||
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Docs>()),
|
||||
&[
|
||||
dist::Docs { host: a },
|
||||
dist::Docs { host: b },
|
||||
]
|
||||
&[dist::Docs { host: a }, dist::Docs { host: b },]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Mingw>()),
|
||||
|
@ -322,68 +234,35 @@ fn dist_with_same_targets_and_hosts() {
|
|||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Rustc>()),
|
||||
&[
|
||||
dist::Rustc {
|
||||
compiler: Compiler { host: a, stage: 2 }
|
||||
},
|
||||
dist::Rustc {
|
||||
compiler: Compiler { host: b, stage: 2 }
|
||||
},
|
||||
dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
|
||||
dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<dist::Std>()),
|
||||
&[
|
||||
dist::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: a,
|
||||
},
|
||||
dist::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: b,
|
||||
},
|
||||
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
|
||||
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
]
|
||||
);
|
||||
assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<compile::Std>()),
|
||||
&[
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 0 },
|
||||
target: a,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: a,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 2 },
|
||||
target: a,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: b,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 2 },
|
||||
target: b,
|
||||
},
|
||||
compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<compile::Assemble>()),
|
||||
&[
|
||||
compile::Assemble {
|
||||
target_compiler: Compiler { host: a, stage: 0 },
|
||||
},
|
||||
compile::Assemble {
|
||||
target_compiler: Compiler { host: a, stage: 1 },
|
||||
},
|
||||
compile::Assemble {
|
||||
target_compiler: Compiler { host: a, stage: 2 },
|
||||
},
|
||||
compile::Assemble {
|
||||
target_compiler: Compiler { host: b, stage: 2 },
|
||||
},
|
||||
compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
|
||||
compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
|
||||
compile::Assemble { target_compiler: Compiler { host: a, stage: 2 } },
|
||||
compile::Assemble { target_compiler: Compiler { host: b, stage: 2 } },
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -401,76 +280,28 @@ fn build_default() {
|
|||
assert_eq!(
|
||||
first(builder.cache.all::<compile::Std>()),
|
||||
&[
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 0 },
|
||||
target: a,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: a,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 2 },
|
||||
target: a,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: b, stage: 2 },
|
||||
target: a,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: b,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 2 },
|
||||
target: b,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: b, stage: 2 },
|
||||
target: b,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 2 },
|
||||
target: c,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: b, stage: 2 },
|
||||
target: c,
|
||||
},
|
||||
compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: b, stage: 2 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
|
||||
compile::Std { compiler: Compiler { host: b, stage: 2 }, target: b },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
|
||||
compile::Std { compiler: Compiler { host: b, stage: 2 }, target: c },
|
||||
]
|
||||
);
|
||||
assert!(!builder.cache.all::<compile::Assemble>().is_empty());
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<compile::Rustc>()),
|
||||
&[
|
||||
compile::Rustc {
|
||||
compiler: Compiler { host: a, stage: 0 },
|
||||
target: a,
|
||||
},
|
||||
compile::Rustc {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: a,
|
||||
},
|
||||
compile::Rustc {
|
||||
compiler: Compiler { host: a, stage: 2 },
|
||||
target: a,
|
||||
},
|
||||
compile::Rustc {
|
||||
compiler: Compiler { host: b, stage: 2 },
|
||||
target: a,
|
||||
},
|
||||
compile::Rustc {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: b,
|
||||
},
|
||||
compile::Rustc {
|
||||
compiler: Compiler { host: a, stage: 2 },
|
||||
target: b,
|
||||
},
|
||||
compile::Rustc {
|
||||
compiler: Compiler { host: b, stage: 2 },
|
||||
target: b,
|
||||
},
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a },
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: a },
|
||||
compile::Rustc { compiler: Compiler { host: b, stage: 2 }, target: a },
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: b },
|
||||
compile::Rustc { compiler: Compiler { host: b, stage: 2 }, target: b },
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -490,76 +321,32 @@ fn build_with_target_flag() {
|
|||
assert_eq!(
|
||||
first(builder.cache.all::<compile::Std>()),
|
||||
&[
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 0 },
|
||||
target: a,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: a,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 2 },
|
||||
target: a,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: b, stage: 2 },
|
||||
target: a,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: b,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 2 },
|
||||
target: b,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: b, stage: 2 },
|
||||
target: b,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: a, stage: 2 },
|
||||
target: c,
|
||||
},
|
||||
compile::Std {
|
||||
compiler: Compiler { host: b, stage: 2 },
|
||||
target: c,
|
||||
},
|
||||
compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: b, stage: 2 }, target: a },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
|
||||
compile::Std { compiler: Compiler { host: b, stage: 2 }, target: b },
|
||||
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
|
||||
compile::Std { compiler: Compiler { host: b, stage: 2 }, target: c },
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<compile::Assemble>()),
|
||||
&[
|
||||
compile::Assemble {
|
||||
target_compiler: Compiler { host: a, stage: 0 },
|
||||
},
|
||||
compile::Assemble {
|
||||
target_compiler: Compiler { host: a, stage: 1 },
|
||||
},
|
||||
compile::Assemble {
|
||||
target_compiler: Compiler { host: a, stage: 2 },
|
||||
},
|
||||
compile::Assemble {
|
||||
target_compiler: Compiler { host: b, stage: 2 },
|
||||
},
|
||||
compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
|
||||
compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
|
||||
compile::Assemble { target_compiler: Compiler { host: a, stage: 2 } },
|
||||
compile::Assemble { target_compiler: Compiler { host: b, stage: 2 } },
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
first(builder.cache.all::<compile::Rustc>()),
|
||||
&[
|
||||
compile::Rustc {
|
||||
compiler: Compiler { host: a, stage: 0 },
|
||||
target: a,
|
||||
},
|
||||
compile::Rustc {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: a,
|
||||
},
|
||||
compile::Rustc {
|
||||
compiler: Compiler { host: a, stage: 1 },
|
||||
target: b,
|
||||
},
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a },
|
||||
compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -585,10 +372,8 @@ fn test_with_no_doc_stage0() {
|
|||
|
||||
let host = INTERNER.intern_str("A");
|
||||
|
||||
builder.run_step_descriptions(
|
||||
&[StepDescription::from::<test::Crate>()],
|
||||
&["src/libstd".into()],
|
||||
);
|
||||
builder
|
||||
.run_step_descriptions(&[StepDescription::from::<test::Crate>()], &["src/libstd".into()]);
|
||||
|
||||
// Ensure we don't build any compiler artifacts.
|
||||
assert!(!builder.cache.contains::<compile::Rustc>());
|
||||
|
@ -607,9 +392,7 @@ fn test_with_no_doc_stage0() {
|
|||
#[test]
|
||||
fn test_exclude() {
|
||||
let mut config = configure(&[], &[]);
|
||||
config.exclude = vec![
|
||||
"src/tools/tidy".into(),
|
||||
];
|
||||
config.exclude = vec!["src/tools/tidy".into()];
|
||||
config.cmd = Subcommand::Test {
|
||||
paths: Vec::new(),
|
||||
test_args: Vec::new(),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::any::{Any, TypeId};
|
||||
use std::borrow::Borrow;
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::{Ord, Ordering, PartialOrd};
|
||||
use std::collections::HashMap;
|
||||
use std::convert::AsRef;
|
||||
use std::ffi::OsStr;
|
||||
|
@ -11,7 +12,6 @@ use std::mem;
|
|||
use std::ops::Deref;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Mutex;
|
||||
use std::cmp::{PartialOrd, Ord, Ordering};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
|
@ -47,7 +47,7 @@ impl<T> Eq for Interned<T> {}
|
|||
|
||||
impl PartialEq<str> for Interned<String> {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
*self == other
|
||||
*self == other
|
||||
}
|
||||
}
|
||||
impl<'a> PartialEq<&'a str> for Interned<String> {
|
||||
|
@ -168,24 +168,21 @@ struct TyIntern<T: Clone + Eq> {
|
|||
|
||||
impl<T: Hash + Clone + Eq> Default for TyIntern<T> {
|
||||
fn default() -> Self {
|
||||
TyIntern {
|
||||
items: Vec::new(),
|
||||
set: Default::default(),
|
||||
}
|
||||
TyIntern { items: Vec::new(), set: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Hash + Clone + Eq> TyIntern<T> {
|
||||
fn intern_borrow<B>(&mut self, item: &B) -> Interned<T>
|
||||
where
|
||||
B: Eq + Hash + ToOwned<Owned=T> + ?Sized,
|
||||
B: Eq + Hash + ToOwned<Owned = T> + ?Sized,
|
||||
T: Borrow<B>,
|
||||
{
|
||||
if let Some(i) = self.set.get(&item) {
|
||||
return *i;
|
||||
}
|
||||
let item = item.to_owned();
|
||||
let interned = Interned(self.items.len(), PhantomData::<*const T>);
|
||||
let interned = Interned(self.items.len(), PhantomData::<*const T>);
|
||||
self.set.insert(item.clone(), interned);
|
||||
self.items.push(item);
|
||||
interned
|
||||
|
@ -195,7 +192,7 @@ impl<T: Hash + Clone + Eq> TyIntern<T> {
|
|||
if let Some(i) = self.set.get(&item) {
|
||||
return *i;
|
||||
}
|
||||
let interned = Interned(self.items.len(), PhantomData::<*const T>);
|
||||
let interned = Interned(self.items.len(), PhantomData::<*const T>);
|
||||
self.set.insert(item.clone(), interned);
|
||||
self.items.push(item);
|
||||
interned
|
||||
|
@ -235,10 +232,12 @@ lazy_static! {
|
|||
/// `get()` method.
|
||||
#[derive(Debug)]
|
||||
pub struct Cache(
|
||||
RefCell<HashMap<
|
||||
TypeId,
|
||||
Box<dyn Any>, // actually a HashMap<Step, Interned<Step::Output>>
|
||||
>>
|
||||
RefCell<
|
||||
HashMap<
|
||||
TypeId,
|
||||
Box<dyn Any>, // actually a HashMap<Step, Interned<Step::Output>>
|
||||
>,
|
||||
>,
|
||||
);
|
||||
|
||||
impl Cache {
|
||||
|
@ -249,10 +248,11 @@ impl Cache {
|
|||
pub fn put<S: Step>(&self, step: S, value: S::Output) {
|
||||
let mut cache = self.0.borrow_mut();
|
||||
let type_id = TypeId::of::<S>();
|
||||
let stepcache = cache.entry(type_id)
|
||||
.or_insert_with(|| Box::new(HashMap::<S, S::Output>::new()))
|
||||
.downcast_mut::<HashMap<S, S::Output>>()
|
||||
.expect("invalid type mapped");
|
||||
let stepcache = cache
|
||||
.entry(type_id)
|
||||
.or_insert_with(|| Box::new(HashMap::<S, S::Output>::new()))
|
||||
.downcast_mut::<HashMap<S, S::Output>>()
|
||||
.expect("invalid type mapped");
|
||||
assert!(!stepcache.contains_key(&step), "processing {:?} a second time", step);
|
||||
stepcache.insert(step, value);
|
||||
}
|
||||
|
@ -260,10 +260,11 @@ impl Cache {
|
|||
pub fn get<S: Step>(&self, step: &S) -> Option<S::Output> {
|
||||
let mut cache = self.0.borrow_mut();
|
||||
let type_id = TypeId::of::<S>();
|
||||
let stepcache = cache.entry(type_id)
|
||||
.or_insert_with(|| Box::new(HashMap::<S, S::Output>::new()))
|
||||
.downcast_mut::<HashMap<S, S::Output>>()
|
||||
.expect("invalid type mapped");
|
||||
let stepcache = cache
|
||||
.entry(type_id)
|
||||
.or_insert_with(|| Box::new(HashMap::<S, S::Output>::new()))
|
||||
.downcast_mut::<HashMap<S, S::Output>>()
|
||||
.expect("invalid type mapped");
|
||||
stepcache.get(step).cloned()
|
||||
}
|
||||
}
|
||||
|
@ -273,7 +274,8 @@ impl Cache {
|
|||
pub fn all<S: Ord + Copy + Step>(&mut self) -> Vec<(S, S::Output)> {
|
||||
let cache = self.0.get_mut();
|
||||
let type_id = TypeId::of::<S>();
|
||||
let mut v = cache.remove(&type_id)
|
||||
let mut v = cache
|
||||
.remove(&type_id)
|
||||
.map(|b| b.downcast::<HashMap<S, S::Output>>().expect("correct type"))
|
||||
.map(|m| m.into_iter().collect::<Vec<_>>())
|
||||
.unwrap_or_default();
|
||||
|
|
|
@ -22,15 +22,15 @@
|
|||
//! everything.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::{env, iter};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::{env, iter};
|
||||
|
||||
use build_helper::output;
|
||||
|
||||
use crate::{Build, GitRepo};
|
||||
use crate::config::Target;
|
||||
use crate::cache::Interned;
|
||||
use crate::config::Target;
|
||||
use crate::{Build, GitRepo};
|
||||
|
||||
// The `cc` crate doesn't provide a way to obtain a path to the detected archiver,
|
||||
// so use some simplified logic here. First we respect the environment variable `AR`, then
|
||||
|
@ -64,14 +64,25 @@ fn cc2ar(cc: &Path, target: &str) -> Option<PathBuf> {
|
|||
pub fn find(build: &mut Build) {
|
||||
// For all targets we're going to need a C compiler for building some shims
|
||||
// and such as well as for being a linker for Rust code.
|
||||
let targets = build.targets.iter().chain(&build.hosts).cloned().chain(iter::once(build.build))
|
||||
.collect::<HashSet<_>>();
|
||||
let targets = build
|
||||
.targets
|
||||
.iter()
|
||||
.chain(&build.hosts)
|
||||
.cloned()
|
||||
.chain(iter::once(build.build))
|
||||
.collect::<HashSet<_>>();
|
||||
for target in targets.into_iter() {
|
||||
let mut cfg = cc::Build::new();
|
||||
cfg.cargo_metadata(false).opt_level(2).warnings(false).debug(false)
|
||||
.target(&target).host(&build.build);
|
||||
cfg.cargo_metadata(false)
|
||||
.opt_level(2)
|
||||
.warnings(false)
|
||||
.debug(false)
|
||||
.target(&target)
|
||||
.host(&build.build);
|
||||
match build.crt_static(target) {
|
||||
Some(a) => { cfg.static_crt(a); }
|
||||
Some(a) => {
|
||||
cfg.static_crt(a);
|
||||
}
|
||||
None => {
|
||||
if target.contains("msvc") {
|
||||
cfg.static_crt(true);
|
||||
|
@ -102,8 +113,13 @@ pub fn find(build: &mut Build) {
|
|||
// If we use llvm-libunwind, we will need a C++ compiler as well for all targets
|
||||
// We'll need one anyways if the target triple is also a host triple
|
||||
let mut cfg = cc::Build::new();
|
||||
cfg.cargo_metadata(false).opt_level(2).warnings(false).debug(false).cpp(true)
|
||||
.target(&target).host(&build.build);
|
||||
cfg.cargo_metadata(false)
|
||||
.opt_level(2)
|
||||
.warnings(false)
|
||||
.debug(false)
|
||||
.cpp(true)
|
||||
.target(&target)
|
||||
.host(&build.build);
|
||||
|
||||
let cxx_configured = if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) {
|
||||
cfg.compiler(cxx);
|
||||
|
@ -133,21 +149,24 @@ pub fn find(build: &mut Build) {
|
|||
}
|
||||
}
|
||||
|
||||
fn set_compiler(cfg: &mut cc::Build,
|
||||
compiler: Language,
|
||||
target: Interned<String>,
|
||||
config: Option<&Target>,
|
||||
build: &Build) {
|
||||
fn set_compiler(
|
||||
cfg: &mut cc::Build,
|
||||
compiler: Language,
|
||||
target: Interned<String>,
|
||||
config: Option<&Target>,
|
||||
build: &Build,
|
||||
) {
|
||||
match &*target {
|
||||
// When compiling for android we may have the NDK configured in the
|
||||
// config.toml in which case we look there. Otherwise the default
|
||||
// compiler already takes into account the triple in question.
|
||||
t if t.contains("android") => {
|
||||
if let Some(ndk) = config.and_then(|c| c.ndk.as_ref()) {
|
||||
let target = target.replace("armv7neon", "arm")
|
||||
.replace("armv7", "arm")
|
||||
.replace("thumbv7neon", "arm")
|
||||
.replace("thumbv7", "arm");
|
||||
let target = target
|
||||
.replace("armv7neon", "arm")
|
||||
.replace("armv7", "arm")
|
||||
.replace("thumbv7neon", "arm")
|
||||
.replace("thumbv7", "arm");
|
||||
let compiler = format!("{}-{}", target, compiler.clang());
|
||||
cfg.compiler(ndk.join("bin").join(compiler));
|
||||
}
|
||||
|
@ -159,7 +178,7 @@ fn set_compiler(cfg: &mut cc::Build,
|
|||
let c = cfg.get_compiler();
|
||||
let gnu_compiler = compiler.gcc();
|
||||
if !c.path().ends_with(gnu_compiler) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
let output = output(c.to_command().arg("--version"));
|
||||
|
@ -168,7 +187,7 @@ fn set_compiler(cfg: &mut cc::Build,
|
|||
None => return,
|
||||
};
|
||||
match output[i + 3..].chars().next().unwrap() {
|
||||
'0' ..= '6' => {}
|
||||
'0'..='6' => {}
|
||||
_ => return,
|
||||
}
|
||||
let alternative = format!("e{}", gnu_compiler);
|
||||
|
|
|
@ -29,31 +29,28 @@ impl GitInfo {
|
|||
pub fn new(ignore_git: bool, dir: &Path) -> GitInfo {
|
||||
// See if this even begins to look like a git dir
|
||||
if ignore_git || !dir.join(".git").exists() {
|
||||
return GitInfo { inner: None }
|
||||
return GitInfo { inner: None };
|
||||
}
|
||||
|
||||
// Make sure git commands work
|
||||
match Command::new("git")
|
||||
.arg("rev-parse")
|
||||
.current_dir(dir)
|
||||
.output()
|
||||
{
|
||||
match Command::new("git").arg("rev-parse").current_dir(dir).output() {
|
||||
Ok(ref out) if out.status.success() => {}
|
||||
_ => return GitInfo { inner: None },
|
||||
}
|
||||
|
||||
// Ok, let's scrape some info
|
||||
let ver_date = output(Command::new("git").current_dir(dir)
|
||||
.arg("log").arg("-1")
|
||||
.arg("--date=short")
|
||||
.arg("--pretty=format:%cd"));
|
||||
let ver_hash = output(Command::new("git").current_dir(dir)
|
||||
.arg("rev-parse").arg("HEAD"));
|
||||
let short_ver_hash = output(Command::new("git")
|
||||
.current_dir(dir)
|
||||
.arg("rev-parse")
|
||||
.arg("--short=9")
|
||||
.arg("HEAD"));
|
||||
let ver_date = output(
|
||||
Command::new("git")
|
||||
.current_dir(dir)
|
||||
.arg("log")
|
||||
.arg("-1")
|
||||
.arg("--date=short")
|
||||
.arg("--pretty=format:%cd"),
|
||||
);
|
||||
let ver_hash = output(Command::new("git").current_dir(dir).arg("rev-parse").arg("HEAD"));
|
||||
let short_ver_hash = output(
|
||||
Command::new("git").current_dir(dir).arg("rev-parse").arg("--short=9").arg("HEAD"),
|
||||
);
|
||||
GitInfo {
|
||||
inner: Some(Info {
|
||||
commit_date: ver_date.trim().to_string(),
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//! Implementation of compiling the compiler and standard library, in "check"-based modes.
|
||||
|
||||
use crate::compile::{run_cargo, std_cargo, rustc_cargo, add_to_sysroot};
|
||||
use crate::builder::{RunConfig, Builder, Kind, ShouldRun, Step};
|
||||
use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
|
||||
use crate::cache::Interned;
|
||||
use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, std_cargo};
|
||||
use crate::tool::{prepare_tool_cargo, SourceType};
|
||||
use crate::{Compiler, Mode};
|
||||
use crate::cache::Interned;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
|
@ -15,7 +15,7 @@ pub struct Std {
|
|||
fn args(kind: Kind) -> Vec<String> {
|
||||
match kind {
|
||||
Kind::Clippy => vec!["--".to_owned(), "--cap-lints".to_owned(), "warn".to_owned()],
|
||||
_ => Vec::new()
|
||||
_ => Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ fn cargo_subcommand(kind: Kind) -> &'static str {
|
|||
Kind::Check => "check",
|
||||
Kind::Clippy => "clippy",
|
||||
Kind::Fix => "fix",
|
||||
_ => unreachable!()
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,9 +37,7 @@ impl Step for Std {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Std {
|
||||
target: run.target,
|
||||
});
|
||||
run.builder.ensure(Std { target: run.target });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
|
@ -50,12 +48,14 @@ impl Step for Std {
|
|||
std_cargo(builder, &compiler, target, &mut cargo);
|
||||
|
||||
builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
|
||||
run_cargo(builder,
|
||||
cargo,
|
||||
args(builder.kind),
|
||||
&libstd_stamp(builder, compiler, target),
|
||||
vec![],
|
||||
true);
|
||||
run_cargo(
|
||||
builder,
|
||||
cargo,
|
||||
args(builder.kind),
|
||||
&libstd_stamp(builder, compiler, target),
|
||||
vec![],
|
||||
true,
|
||||
);
|
||||
|
||||
let libdir = builder.sysroot_libdir(compiler, target);
|
||||
let hostdir = builder.sysroot_libdir(compiler, compiler.host);
|
||||
|
@ -78,9 +78,7 @@ impl Step for Rustc {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Rustc {
|
||||
target: run.target,
|
||||
});
|
||||
run.builder.ensure(Rustc { target: run.target });
|
||||
}
|
||||
|
||||
/// Builds the compiler.
|
||||
|
@ -94,17 +92,19 @@ impl Step for Rustc {
|
|||
|
||||
builder.ensure(Std { target });
|
||||
|
||||
let mut cargo = builder.cargo(compiler, Mode::Rustc, target,
|
||||
cargo_subcommand(builder.kind));
|
||||
let mut cargo =
|
||||
builder.cargo(compiler, Mode::Rustc, target, cargo_subcommand(builder.kind));
|
||||
rustc_cargo(builder, &mut cargo, target);
|
||||
|
||||
builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target));
|
||||
run_cargo(builder,
|
||||
cargo,
|
||||
args(builder.kind),
|
||||
&librustc_stamp(builder, compiler, target),
|
||||
vec![],
|
||||
true);
|
||||
run_cargo(
|
||||
builder,
|
||||
cargo,
|
||||
args(builder.kind),
|
||||
&librustc_stamp(builder, compiler, target),
|
||||
vec![],
|
||||
true,
|
||||
);
|
||||
|
||||
let libdir = builder.sysroot_libdir(compiler, target);
|
||||
let hostdir = builder.sysroot_libdir(compiler, compiler.host);
|
||||
|
@ -127,9 +127,7 @@ impl Step for Rustdoc {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Rustdoc {
|
||||
target: run.target,
|
||||
});
|
||||
run.builder.ensure(Rustdoc { target: run.target });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
|
@ -138,22 +136,26 @@ impl Step for Rustdoc {
|
|||
|
||||
builder.ensure(Rustc { target });
|
||||
|
||||
let cargo = prepare_tool_cargo(builder,
|
||||
compiler,
|
||||
Mode::ToolRustc,
|
||||
target,
|
||||
cargo_subcommand(builder.kind),
|
||||
"src/tools/rustdoc",
|
||||
SourceType::InTree,
|
||||
&[]);
|
||||
let cargo = prepare_tool_cargo(
|
||||
builder,
|
||||
compiler,
|
||||
Mode::ToolRustc,
|
||||
target,
|
||||
cargo_subcommand(builder.kind),
|
||||
"src/tools/rustdoc",
|
||||
SourceType::InTree,
|
||||
&[],
|
||||
);
|
||||
|
||||
println!("Checking rustdoc artifacts ({} -> {})", &compiler.host, target);
|
||||
run_cargo(builder,
|
||||
cargo,
|
||||
args(builder.kind),
|
||||
&rustdoc_stamp(builder, compiler, target),
|
||||
vec![],
|
||||
true);
|
||||
run_cargo(
|
||||
builder,
|
||||
cargo,
|
||||
args(builder.kind),
|
||||
&rustdoc_stamp(builder, compiler, target),
|
||||
vec![],
|
||||
true,
|
||||
);
|
||||
|
||||
let libdir = builder.sysroot_libdir(compiler, target);
|
||||
let hostdir = builder.sysroot_libdir(compiler, compiler.host);
|
||||
|
@ -188,6 +190,5 @@ pub fn rustdoc_stamp(
|
|||
compiler: Compiler,
|
||||
target: Interned<String>,
|
||||
) -> PathBuf {
|
||||
builder.cargo_out(compiler, Mode::ToolRustc, target)
|
||||
.join(".rustdoc-check.stamp")
|
||||
builder.cargo_out(compiler, Mode::ToolRustc, target).join(".rustdoc-check.stamp")
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ pub fn clean(build: &Build, all: bool) {
|
|||
for entry in entries {
|
||||
let entry = t!(entry);
|
||||
if entry.file_name().to_str() == Some("llvm") {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
let path = t!(entry.path().canonicalize());
|
||||
rm_rf(&path);
|
||||
|
@ -47,7 +47,7 @@ fn rm_rf(path: &Path) {
|
|||
return;
|
||||
}
|
||||
panic!("failed to get metadata for file {}: {}", path.display(), e);
|
||||
},
|
||||
}
|
||||
Ok(metadata) => {
|
||||
if metadata.file_type().is_file() || metadata.file_type().is_symlink() {
|
||||
do_op(path, "remove file", |p| fs::remove_file(p));
|
||||
|
@ -58,20 +58,20 @@ fn rm_rf(path: &Path) {
|
|||
rm_rf(&t!(file).path());
|
||||
}
|
||||
do_op(path, "remove dir", |p| fs::remove_dir(p));
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn do_op<F>(path: &Path, desc: &str, mut f: F)
|
||||
where F: FnMut(&Path) -> io::Result<()>
|
||||
where
|
||||
F: FnMut(&Path) -> io::Result<()>,
|
||||
{
|
||||
match f(path) {
|
||||
Ok(()) => {}
|
||||
// On windows we can't remove a readonly file, and git will often clone files as readonly.
|
||||
// As a result, we have some special logic to remove readonly files on windows.
|
||||
// This is also the reason that we can't use things like fs::remove_dir_all().
|
||||
Err(ref e) if cfg!(windows) &&
|
||||
e.kind() == ErrorKind::PermissionDenied => {
|
||||
Err(ref e) if cfg!(windows) && e.kind() == ErrorKind::PermissionDenied => {
|
||||
let mut p = t!(path.symlink_metadata()).permissions();
|
||||
p.set_readonly(false);
|
||||
t!(fs::set_permissions(path, p));
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
use std::borrow::Cow;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io::BufReader;
|
||||
use std::io::prelude::*;
|
||||
use std::io::BufReader;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, Stdio, exit};
|
||||
use std::process::{exit, Command, Stdio};
|
||||
use std::str;
|
||||
|
||||
use build_helper::{output, t, up_to_date};
|
||||
|
@ -20,14 +20,14 @@ use filetime::FileTime;
|
|||
use serde::Deserialize;
|
||||
use serde_json;
|
||||
|
||||
use crate::dist;
|
||||
use crate::builder::Cargo;
|
||||
use crate::util::{exe, is_dylib};
|
||||
use crate::{Compiler, Mode, GitRepo};
|
||||
use crate::dist;
|
||||
use crate::native;
|
||||
use crate::util::{exe, is_dylib};
|
||||
use crate::{Compiler, GitRepo, Mode};
|
||||
|
||||
use crate::cache::{INTERNER, Interned};
|
||||
use crate::builder::{Step, RunConfig, ShouldRun, Builder, Kind};
|
||||
use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
|
||||
use crate::cache::{Interned, INTERNER};
|
||||
|
||||
#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Std {
|
||||
|
@ -61,11 +61,7 @@ impl Step for Std {
|
|||
|
||||
if builder.config.keep_stage.contains(&compiler.stage) {
|
||||
builder.info("Warning: Using a potentially old libstd. This may not behave well.");
|
||||
builder.ensure(StdLink {
|
||||
compiler,
|
||||
target_compiler: compiler,
|
||||
target,
|
||||
});
|
||||
builder.ensure(StdLink { compiler, target_compiler: compiler, target });
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -73,10 +69,7 @@ impl Step for Std {
|
|||
|
||||
let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
|
||||
if compiler_to_use != compiler {
|
||||
builder.ensure(Std {
|
||||
compiler: compiler_to_use,
|
||||
target,
|
||||
});
|
||||
builder.ensure(Std { compiler: compiler_to_use, target });
|
||||
builder.info(&format!("Uplifting stage1 std ({} -> {})", compiler_to_use.host, target));
|
||||
|
||||
// Even if we're not building std this stage, the new sysroot must
|
||||
|
@ -96,14 +89,18 @@ impl Step for Std {
|
|||
let mut cargo = builder.cargo(compiler, Mode::Std, target, "build");
|
||||
std_cargo(builder, &compiler, target, &mut cargo);
|
||||
|
||||
builder.info(&format!("Building stage{} std artifacts ({} -> {})", compiler.stage,
|
||||
&compiler.host, target));
|
||||
run_cargo(builder,
|
||||
cargo,
|
||||
vec![],
|
||||
&libstd_stamp(builder, compiler, target),
|
||||
target_deps,
|
||||
false);
|
||||
builder.info(&format!(
|
||||
"Building stage{} std artifacts ({} -> {})",
|
||||
compiler.stage, &compiler.host, target
|
||||
));
|
||||
run_cargo(
|
||||
builder,
|
||||
cargo,
|
||||
vec![],
|
||||
&libstd_stamp(builder, compiler, target),
|
||||
target_deps,
|
||||
false,
|
||||
);
|
||||
|
||||
builder.ensure(StdLink {
|
||||
compiler: builder.compiler(compiler.stage, builder.config.build),
|
||||
|
@ -114,19 +111,18 @@ impl Step for Std {
|
|||
}
|
||||
|
||||
/// Copies third party objects needed by various targets.
|
||||
fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: Interned<String>)
|
||||
-> Vec<PathBuf>
|
||||
{
|
||||
fn copy_third_party_objects(
|
||||
builder: &Builder<'_>,
|
||||
compiler: &Compiler,
|
||||
target: Interned<String>,
|
||||
) -> Vec<PathBuf> {
|
||||
let libdir = builder.sysroot_libdir(*compiler, target);
|
||||
|
||||
let mut target_deps = vec![];
|
||||
|
||||
let mut copy_and_stamp = |sourcedir: &Path, name: &str| {
|
||||
let target = libdir.join(name);
|
||||
builder.copy(
|
||||
&sourcedir.join(name),
|
||||
&target,
|
||||
);
|
||||
builder.copy(&sourcedir.join(name), &target);
|
||||
target_deps.push(target);
|
||||
};
|
||||
|
||||
|
@ -162,10 +158,12 @@ fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target:
|
|||
|
||||
/// Configure cargo to compile the standard library, adding appropriate env vars
|
||||
/// and such.
|
||||
pub fn std_cargo(builder: &Builder<'_>,
|
||||
compiler: &Compiler,
|
||||
target: Interned<String>,
|
||||
cargo: &mut Cargo) {
|
||||
pub fn std_cargo(
|
||||
builder: &Builder<'_>,
|
||||
compiler: &Compiler,
|
||||
target: Interned<String>,
|
||||
cargo: &mut Cargo,
|
||||
) {
|
||||
if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
|
||||
cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
|
||||
}
|
||||
|
@ -216,14 +214,14 @@ pub fn std_cargo(builder: &Builder<'_>,
|
|||
// missing
|
||||
// We also only build the runtimes when --enable-sanitizers (or its
|
||||
// config.toml equivalent) is used
|
||||
let llvm_config = builder.ensure(native::Llvm {
|
||||
target: builder.config.build,
|
||||
});
|
||||
let llvm_config = builder.ensure(native::Llvm { target: builder.config.build });
|
||||
cargo.env("LLVM_CONFIG", llvm_config);
|
||||
cargo.env("RUSTC_BUILD_SANITIZERS", "1");
|
||||
}
|
||||
|
||||
cargo.arg("--features").arg(features)
|
||||
cargo
|
||||
.arg("--features")
|
||||
.arg(features)
|
||||
.arg("--manifest-path")
|
||||
.arg(builder.src.join("src/libtest/Cargo.toml"));
|
||||
|
||||
|
@ -271,12 +269,10 @@ impl Step for StdLink {
|
|||
let compiler = self.compiler;
|
||||
let target_compiler = self.target_compiler;
|
||||
let target = self.target;
|
||||
builder.info(&format!("Copying stage{} std from stage{} ({} -> {} / {})",
|
||||
target_compiler.stage,
|
||||
compiler.stage,
|
||||
&compiler.host,
|
||||
target_compiler.host,
|
||||
target));
|
||||
builder.info(&format!(
|
||||
"Copying stage{} std from stage{} ({} -> {} / {})",
|
||||
target_compiler.stage, compiler.stage, &compiler.host, target_compiler.host, target
|
||||
));
|
||||
let libdir = builder.sysroot_libdir(target_compiler, target);
|
||||
let hostdir = builder.sysroot_libdir(target_compiler, compiler.host);
|
||||
add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
|
||||
|
@ -337,7 +333,7 @@ impl Step for StartupObjects {
|
|||
let for_compiler = self.compiler;
|
||||
let target = self.target;
|
||||
if !target.contains("windows-gnu") {
|
||||
return vec![]
|
||||
return vec![];
|
||||
}
|
||||
|
||||
let mut target_deps = vec![];
|
||||
|
@ -352,12 +348,17 @@ impl Step for StartupObjects {
|
|||
let dst_file = &dst_dir.join(file.to_string() + ".o");
|
||||
if !up_to_date(src_file, dst_file) {
|
||||
let mut cmd = Command::new(&builder.initial_rustc);
|
||||
builder.run(cmd.env("RUSTC_BOOTSTRAP", "1")
|
||||
.arg("--cfg").arg("bootstrap")
|
||||
.arg("--target").arg(target)
|
||||
.arg("--emit=obj")
|
||||
.arg("-o").arg(dst_file)
|
||||
.arg(src_file));
|
||||
builder.run(
|
||||
cmd.env("RUSTC_BOOTSTRAP", "1")
|
||||
.arg("--cfg")
|
||||
.arg("bootstrap")
|
||||
.arg("--target")
|
||||
.arg(target)
|
||||
.arg("--emit=obj")
|
||||
.arg("-o")
|
||||
.arg(dst_file)
|
||||
.arg(src_file),
|
||||
);
|
||||
}
|
||||
|
||||
let target = sysroot_dir.join(file.to_string() + ".o");
|
||||
|
@ -366,10 +367,7 @@ impl Step for StartupObjects {
|
|||
}
|
||||
|
||||
for obj in ["crt2.o", "dllcrt2.o"].iter() {
|
||||
let src = compiler_file(builder,
|
||||
builder.cc(target),
|
||||
target,
|
||||
obj);
|
||||
let src = compiler_file(builder, builder.cc(target), target, obj);
|
||||
let target = sysroot_dir.join(obj);
|
||||
builder.copy(&src, &target);
|
||||
target_deps.push(target);
|
||||
|
@ -414,22 +412,15 @@ impl Step for Rustc {
|
|||
|
||||
if builder.config.keep_stage.contains(&compiler.stage) {
|
||||
builder.info("Warning: Using a potentially old librustc. This may not behave well.");
|
||||
builder.ensure(RustcLink {
|
||||
compiler,
|
||||
target_compiler: compiler,
|
||||
target,
|
||||
});
|
||||
builder.ensure(RustcLink { compiler, target_compiler: compiler, target });
|
||||
return;
|
||||
}
|
||||
|
||||
let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
|
||||
if compiler_to_use != compiler {
|
||||
builder.ensure(Rustc {
|
||||
compiler: compiler_to_use,
|
||||
target,
|
||||
});
|
||||
builder.info(&format!("Uplifting stage1 rustc ({} -> {})",
|
||||
builder.config.build, target));
|
||||
builder.ensure(Rustc { compiler: compiler_to_use, target });
|
||||
builder
|
||||
.info(&format!("Uplifting stage1 rustc ({} -> {})", builder.config.build, target));
|
||||
builder.ensure(RustcLink {
|
||||
compiler: compiler_to_use,
|
||||
target_compiler: compiler,
|
||||
|
@ -447,14 +438,18 @@ impl Step for Rustc {
|
|||
let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "build");
|
||||
rustc_cargo(builder, &mut cargo, target);
|
||||
|
||||
builder.info(&format!("Building stage{} compiler artifacts ({} -> {})",
|
||||
compiler.stage, &compiler.host, target));
|
||||
run_cargo(builder,
|
||||
cargo,
|
||||
vec![],
|
||||
&librustc_stamp(builder, compiler, target),
|
||||
vec![],
|
||||
false);
|
||||
builder.info(&format!(
|
||||
"Building stage{} compiler artifacts ({} -> {})",
|
||||
compiler.stage, &compiler.host, target
|
||||
));
|
||||
run_cargo(
|
||||
builder,
|
||||
cargo,
|
||||
vec![],
|
||||
&librustc_stamp(builder, compiler, target),
|
||||
vec![],
|
||||
false,
|
||||
);
|
||||
|
||||
// We used to build librustc_codegen_llvm as a separate step,
|
||||
// which produced a dylib that the compiler would dlopen() at runtime.
|
||||
|
@ -503,19 +498,22 @@ impl Step for Rustc {
|
|||
}
|
||||
|
||||
pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo, target: Interned<String>) {
|
||||
cargo.arg("--features").arg(builder.rustc_features())
|
||||
.arg("--manifest-path")
|
||||
.arg(builder.src.join("src/rustc/Cargo.toml"));
|
||||
cargo
|
||||
.arg("--features")
|
||||
.arg(builder.rustc_features())
|
||||
.arg("--manifest-path")
|
||||
.arg(builder.src.join("src/rustc/Cargo.toml"));
|
||||
rustc_cargo_env(builder, cargo, target);
|
||||
}
|
||||
|
||||
pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: Interned<String>) {
|
||||
// Set some configuration variables picked up by build scripts and
|
||||
// the compiler alike
|
||||
cargo.env("CFG_RELEASE", builder.rust_release())
|
||||
.env("CFG_RELEASE_CHANNEL", &builder.config.channel)
|
||||
.env("CFG_VERSION", builder.rust_version())
|
||||
.env("CFG_PREFIX", builder.config.prefix.clone().unwrap_or_default());
|
||||
cargo
|
||||
.env("CFG_RELEASE", builder.rust_release())
|
||||
.env("CFG_RELEASE_CHANNEL", &builder.config.channel)
|
||||
.env("CFG_VERSION", builder.rust_version())
|
||||
.env("CFG_PREFIX", builder.config.prefix.clone().unwrap_or_default());
|
||||
|
||||
let libdir_relative = builder.config.libdir_relative().unwrap_or(Path::new("lib"));
|
||||
cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
|
||||
|
@ -561,14 +559,12 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: Interne
|
|||
}
|
||||
// Building with a static libstdc++ is only supported on linux right now,
|
||||
// not for MSVC or macOS
|
||||
if builder.config.llvm_static_stdcpp &&
|
||||
!target.contains("freebsd") &&
|
||||
!target.contains("msvc") &&
|
||||
!target.contains("apple") {
|
||||
let file = compiler_file(builder,
|
||||
builder.cxx(target).unwrap(),
|
||||
target,
|
||||
"libstdc++.a");
|
||||
if builder.config.llvm_static_stdcpp
|
||||
&& !target.contains("freebsd")
|
||||
&& !target.contains("msvc")
|
||||
&& !target.contains("apple")
|
||||
{
|
||||
let file = compiler_file(builder, builder.cxx(target).unwrap(), target, "libstdc++.a");
|
||||
cargo.env("LLVM_STATIC_STDCPP", file);
|
||||
}
|
||||
if builder.config.llvm_link_shared || builder.config.llvm_thin_lto {
|
||||
|
@ -602,17 +598,15 @@ impl Step for RustcLink {
|
|||
let compiler = self.compiler;
|
||||
let target_compiler = self.target_compiler;
|
||||
let target = self.target;
|
||||
builder.info(&format!("Copying stage{} rustc from stage{} ({} -> {} / {})",
|
||||
target_compiler.stage,
|
||||
compiler.stage,
|
||||
&compiler.host,
|
||||
target_compiler.host,
|
||||
target));
|
||||
builder.info(&format!(
|
||||
"Copying stage{} rustc from stage{} ({} -> {} / {})",
|
||||
target_compiler.stage, compiler.stage, &compiler.host, target_compiler.host, target
|
||||
));
|
||||
add_to_sysroot(
|
||||
builder,
|
||||
&builder.sysroot_libdir(target_compiler, target),
|
||||
&builder.sysroot_libdir(target_compiler, compiler.host),
|
||||
&librustc_stamp(builder, compiler, target)
|
||||
&librustc_stamp(builder, compiler, target),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -706,8 +700,10 @@ impl Step for Assemble {
|
|||
let target_compiler = self.target_compiler;
|
||||
|
||||
if target_compiler.stage == 0 {
|
||||
assert_eq!(builder.config.build, target_compiler.host,
|
||||
"Cannot obtain compiler for non-native build triple at stage 0");
|
||||
assert_eq!(
|
||||
builder.config.build, target_compiler.host,
|
||||
"Cannot obtain compiler for non-native build triple at stage 0"
|
||||
);
|
||||
// The stage 0 compiler for the build triple is always pre-built.
|
||||
return target_compiler;
|
||||
}
|
||||
|
@ -728,23 +724,17 @@ impl Step for Assemble {
|
|||
//
|
||||
// FIXME: It may be faster if we build just a stage 1 compiler and then
|
||||
// use that to bootstrap this compiler forward.
|
||||
let build_compiler =
|
||||
builder.compiler(target_compiler.stage - 1, builder.config.build);
|
||||
let build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build);
|
||||
|
||||
// Build the libraries for this compiler to link to (i.e., the libraries
|
||||
// it uses at runtime). NOTE: Crates the target compiler compiles don't
|
||||
// link to these. (FIXME: Is that correct? It seems to be correct most
|
||||
// of the time but I think we do link to these for stage2/bin compilers
|
||||
// when not performing a full bootstrap).
|
||||
builder.ensure(Rustc {
|
||||
compiler: build_compiler,
|
||||
target: target_compiler.host,
|
||||
});
|
||||
builder.ensure(Rustc { compiler: build_compiler, target: target_compiler.host });
|
||||
|
||||
let lld_install = if builder.config.lld_enabled {
|
||||
Some(builder.ensure(native::Lld {
|
||||
target: target_compiler.host,
|
||||
}))
|
||||
Some(builder.ensure(native::Lld { target: target_compiler.host }))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -801,7 +791,7 @@ pub fn add_to_sysroot(
|
|||
builder: &Builder<'_>,
|
||||
sysroot_dst: &Path,
|
||||
sysroot_host_dst: &Path,
|
||||
stamp: &Path
|
||||
stamp: &Path,
|
||||
) {
|
||||
t!(fs::create_dir_all(&sysroot_dst));
|
||||
t!(fs::create_dir_all(&sysroot_host_dst));
|
||||
|
@ -814,14 +804,14 @@ pub fn add_to_sysroot(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn run_cargo(builder: &Builder<'_>,
|
||||
cargo: Cargo,
|
||||
tail_args: Vec<String>,
|
||||
stamp: &Path,
|
||||
additional_target_deps: Vec<PathBuf>,
|
||||
is_check: bool)
|
||||
-> Vec<PathBuf>
|
||||
{
|
||||
pub fn run_cargo(
|
||||
builder: &Builder<'_>,
|
||||
cargo: Cargo,
|
||||
tail_args: Vec<String>,
|
||||
stamp: &Path,
|
||||
additional_target_deps: Vec<PathBuf>,
|
||||
is_check: bool,
|
||||
) -> Vec<PathBuf> {
|
||||
if builder.config.dry_run {
|
||||
return Vec::new();
|
||||
}
|
||||
|
@ -831,9 +821,12 @@ pub fn run_cargo(builder: &Builder<'_>,
|
|||
// `target_deps_dir` looks like $dir/$target/release/deps
|
||||
let target_deps_dir = target_root_dir.join("deps");
|
||||
// `host_root_dir` looks like $dir/release
|
||||
let host_root_dir = target_root_dir.parent().unwrap() // chop off `release`
|
||||
.parent().unwrap() // chop off `$target`
|
||||
.join(target_root_dir.file_name().unwrap());
|
||||
let host_root_dir = target_root_dir
|
||||
.parent()
|
||||
.unwrap() // chop off `release`
|
||||
.parent()
|
||||
.unwrap() // chop off `$target`
|
||||
.join(target_root_dir.file_name().unwrap());
|
||||
|
||||
// Spawn Cargo slurping up its JSON output. We'll start building up the
|
||||
// `deps` array of all files it generated along with a `toplevel` array of
|
||||
|
@ -844,20 +837,19 @@ pub fn run_cargo(builder: &Builder<'_>,
|
|||
let (filenames, crate_types) = match msg {
|
||||
CargoMessage::CompilerArtifact {
|
||||
filenames,
|
||||
target: CargoTarget {
|
||||
crate_types,
|
||||
},
|
||||
target: CargoTarget { crate_types },
|
||||
..
|
||||
} => (filenames, crate_types),
|
||||
_ => return,
|
||||
};
|
||||
for filename in filenames {
|
||||
// Skip files like executables
|
||||
if !filename.ends_with(".rlib") &&
|
||||
!filename.ends_with(".lib") &&
|
||||
!filename.ends_with(".a") &&
|
||||
!is_dylib(&filename) &&
|
||||
!(is_check && filename.ends_with(".rmeta")) {
|
||||
if !filename.ends_with(".rlib")
|
||||
&& !filename.ends_with(".lib")
|
||||
&& !filename.ends_with(".a")
|
||||
&& !is_dylib(&filename)
|
||||
&& !(is_check && filename.ends_with(".rmeta"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -913,14 +905,13 @@ pub fn run_cargo(builder: &Builder<'_>,
|
|||
.collect::<Vec<_>>();
|
||||
for (prefix, extension, expected_len) in toplevel {
|
||||
let candidates = contents.iter().filter(|&&(_, ref filename, ref meta)| {
|
||||
filename.starts_with(&prefix[..]) &&
|
||||
filename[prefix.len()..].starts_with("-") &&
|
||||
filename.ends_with(&extension[..]) &&
|
||||
meta.len() == expected_len
|
||||
});
|
||||
let max = candidates.max_by_key(|&&(_, _, ref metadata)| {
|
||||
FileTime::from_last_modification_time(metadata)
|
||||
filename.starts_with(&prefix[..])
|
||||
&& filename[prefix.len()..].starts_with("-")
|
||||
&& filename.ends_with(&extension[..])
|
||||
&& meta.len() == expected_len
|
||||
});
|
||||
let max = candidates
|
||||
.max_by_key(|&&(_, _, ref metadata)| FileTime::from_last_modification_time(metadata));
|
||||
let path_to_add = match max {
|
||||
Some(triple) => triple.0.to_str().unwrap(),
|
||||
None => panic!("no output generated for {:?} {:?}", prefix, extension),
|
||||
|
@ -960,7 +951,7 @@ pub fn stream_cargo(
|
|||
// Instruct Cargo to give us json messages on stdout, critically leaving
|
||||
// stderr as piped so we can get those pretty colors.
|
||||
let mut message_format = String::from("json-render-diagnostics");
|
||||
if let Some(s) = &builder.config.rustc_error_format {
|
||||
if let Some(s) = &builder.config.rustc_error_format {
|
||||
message_format.push_str(",json-diagnostic-");
|
||||
message_format.push_str(s);
|
||||
}
|
||||
|
@ -985,17 +976,18 @@ pub fn stream_cargo(
|
|||
match serde_json::from_str::<CargoMessage<'_>>(&line) {
|
||||
Ok(msg) => cb(msg),
|
||||
// If this was informational, just print it out and continue
|
||||
Err(_) => println!("{}", line)
|
||||
Err(_) => println!("{}", line),
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure Cargo actually succeeded after we read all of its stdout.
|
||||
let status = t!(child.wait());
|
||||
if !status.success() {
|
||||
eprintln!("command did not execute successfully: {:?}\n\
|
||||
eprintln!(
|
||||
"command did not execute successfully: {:?}\n\
|
||||
expected success, got: {}",
|
||||
cargo,
|
||||
status);
|
||||
cargo, status
|
||||
);
|
||||
}
|
||||
status.success()
|
||||
}
|
||||
|
|
|
@ -3,20 +3,20 @@
|
|||
//! This module implements parsing `config.toml` configuration files to tweak
|
||||
//! how the build runs.
|
||||
|
||||
use std::cmp;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process;
|
||||
use std::cmp;
|
||||
|
||||
use build_helper::t;
|
||||
use toml;
|
||||
use serde::Deserialize;
|
||||
use crate::cache::{INTERNER, Interned};
|
||||
use crate::cache::{Interned, INTERNER};
|
||||
use crate::flags::Flags;
|
||||
pub use crate::flags::Subcommand;
|
||||
use build_helper::t;
|
||||
use serde::Deserialize;
|
||||
use toml;
|
||||
|
||||
/// Global configuration for the entire build and/or bootstrap.
|
||||
///
|
||||
|
@ -420,17 +420,22 @@ impl Config {
|
|||
let has_targets = !flags.target.is_empty();
|
||||
config.skip_only_host_steps = !has_hosts && has_targets;
|
||||
|
||||
let toml = file.map(|file| {
|
||||
let contents = t!(fs::read_to_string(&file));
|
||||
match toml::from_str(&contents) {
|
||||
Ok(table) => table,
|
||||
Err(err) => {
|
||||
println!("failed to parse TOML configuration '{}': {}",
|
||||
file.display(), err);
|
||||
process::exit(2);
|
||||
let toml = file
|
||||
.map(|file| {
|
||||
let contents = t!(fs::read_to_string(&file));
|
||||
match toml::from_str(&contents) {
|
||||
Ok(table) => table,
|
||||
Err(err) => {
|
||||
println!(
|
||||
"failed to parse TOML configuration '{}': {}",
|
||||
file.display(),
|
||||
err
|
||||
);
|
||||
process::exit(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).unwrap_or_else(|| TomlConfig::default());
|
||||
})
|
||||
.unwrap_or_else(|| TomlConfig::default());
|
||||
|
||||
let build = toml.build.clone().unwrap_or_default();
|
||||
// set by bootstrap.py
|
||||
|
@ -441,24 +446,15 @@ impl Config {
|
|||
config.hosts.push(host);
|
||||
}
|
||||
}
|
||||
for target in config.hosts.iter().cloned()
|
||||
.chain(build.target.iter().map(|s| INTERNER.intern_str(s)))
|
||||
for target in
|
||||
config.hosts.iter().cloned().chain(build.target.iter().map(|s| INTERNER.intern_str(s)))
|
||||
{
|
||||
if !config.targets.contains(&target) {
|
||||
config.targets.push(target);
|
||||
}
|
||||
}
|
||||
config.hosts = if !flags.host.is_empty() {
|
||||
flags.host
|
||||
} else {
|
||||
config.hosts
|
||||
};
|
||||
config.targets = if !flags.target.is_empty() {
|
||||
flags.target
|
||||
} else {
|
||||
config.targets
|
||||
};
|
||||
|
||||
config.hosts = if !flags.host.is_empty() { flags.host } else { config.hosts };
|
||||
config.targets = if !flags.target.is_empty() { flags.target } else { config.targets };
|
||||
|
||||
config.nodejs = build.nodejs.map(PathBuf::from);
|
||||
config.gdb = build.gdb.map(PathBuf::from);
|
||||
|
@ -507,9 +503,7 @@ impl Config {
|
|||
|
||||
if let Some(ref llvm) = toml.llvm {
|
||||
match llvm.ccache {
|
||||
Some(StringOrBool::String(ref s)) => {
|
||||
config.ccache = Some(s.to_string())
|
||||
}
|
||||
Some(StringOrBool::String(ref s)) => config.ccache = Some(s.to_string()),
|
||||
Some(StringOrBool::Bool(true)) => {
|
||||
config.ccache = Some("ccache".to_string());
|
||||
}
|
||||
|
@ -574,9 +568,8 @@ impl Config {
|
|||
set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
|
||||
|
||||
if let Some(ref backends) = rust.codegen_backends {
|
||||
config.rust_codegen_backends = backends.iter()
|
||||
.map(|s| INTERNER.intern_str(s))
|
||||
.collect();
|
||||
config.rust_codegen_backends =
|
||||
backends.iter().map(|s| INTERNER.intern_str(s)).collect();
|
||||
}
|
||||
|
||||
config.rust_codegen_units = rust.codegen_units.map(threads_from_config);
|
||||
|
@ -634,9 +627,11 @@ impl Config {
|
|||
config.rust_debug_assertions = debug_assertions.unwrap_or(default);
|
||||
|
||||
let with_defaults = |debuginfo_level_specific: Option<u32>| {
|
||||
debuginfo_level_specific
|
||||
.or(debuginfo_level)
|
||||
.unwrap_or(if debug == Some(true) { 2 } else { 0 })
|
||||
debuginfo_level_specific.or(debuginfo_level).unwrap_or(if debug == Some(true) {
|
||||
2
|
||||
} else {
|
||||
0
|
||||
})
|
||||
};
|
||||
config.rust_debuginfo_level_rustc = with_defaults(debuginfo_level_rustc);
|
||||
config.rust_debuginfo_level_std = with_defaults(debuginfo_level_std);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,17 +10,17 @@
|
|||
use std::collections::HashSet;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::{PathBuf, Path};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::Mode;
|
||||
use build_helper::{t, up_to_date};
|
||||
|
||||
use crate::util::symlink_dir;
|
||||
use crate::builder::{Builder, Compiler, RunConfig, ShouldRun, Step};
|
||||
use crate::tool::{self, prepare_tool_cargo, Tool, SourceType};
|
||||
use crate::cache::{Interned, INTERNER};
|
||||
use crate::compile;
|
||||
use crate::cache::{INTERNER, Interned};
|
||||
use crate::config::Config;
|
||||
use crate::tool::{self, prepare_tool_cargo, SourceType, Tool};
|
||||
use crate::util::symlink_dir;
|
||||
|
||||
macro_rules! book {
|
||||
($($name:ident, $path:expr, $book_name:expr;)+) => {
|
||||
|
@ -88,15 +88,11 @@ impl Step for UnstableBook {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(UnstableBook {
|
||||
target: run.target,
|
||||
});
|
||||
run.builder.ensure(UnstableBook { target: run.target });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
builder.ensure(UnstableBookGen {
|
||||
target: self.target,
|
||||
});
|
||||
builder.ensure(UnstableBookGen { target: self.target });
|
||||
builder.ensure(RustbookSrc {
|
||||
target: self.target,
|
||||
name: INTERNER.intern_str("unstable-book"),
|
||||
|
@ -121,10 +117,7 @@ impl Step for CargoBook {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(CargoBook {
|
||||
target: run.target,
|
||||
name: INTERNER.intern_str("cargo"),
|
||||
});
|
||||
run.builder.ensure(CargoBook { target: run.target, name: INTERNER.intern_str("cargo") });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
|
@ -141,11 +134,7 @@ impl Step for CargoBook {
|
|||
|
||||
let _ = fs::remove_dir_all(&out);
|
||||
|
||||
builder.run(builder.tool_cmd(Tool::Rustbook)
|
||||
.arg("build")
|
||||
.arg(&src)
|
||||
.arg("-d")
|
||||
.arg(out));
|
||||
builder.run(builder.tool_cmd(Tool::Rustbook).arg("build").arg(&src).arg("-d").arg(out));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,16 +169,12 @@ impl Step for RustbookSrc {
|
|||
let rustbook = builder.tool_exe(Tool::Rustbook);
|
||||
let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
|
||||
if up_to_date(&src, &index) && up_to_date(&rustbook, &index) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
builder.info(&format!("Rustbook ({}) - {}", target, name));
|
||||
let _ = fs::remove_dir_all(&out);
|
||||
|
||||
builder.run(rustbook_cmd
|
||||
.arg("build")
|
||||
.arg(&src)
|
||||
.arg("-d")
|
||||
.arg(out));
|
||||
builder.run(rustbook_cmd.arg("build").arg(&src).arg("-d").arg(out));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,10 +247,7 @@ impl Step for TheBook {
|
|||
});
|
||||
|
||||
// build the version info page and CSS
|
||||
builder.ensure(Standalone {
|
||||
compiler,
|
||||
target,
|
||||
});
|
||||
builder.ensure(Standalone { compiler, target });
|
||||
|
||||
// build the redirect pages
|
||||
builder.info(&format!("Documenting book redirect pages ({})", target));
|
||||
|
@ -297,13 +279,20 @@ fn invoke_rustdoc(
|
|||
|
||||
let out = out.join("book");
|
||||
|
||||
cmd.arg("--html-after-content").arg(&footer)
|
||||
.arg("--html-before-content").arg(&version_info)
|
||||
.arg("--html-in-header").arg(&header)
|
||||
cmd.arg("--html-after-content")
|
||||
.arg(&footer)
|
||||
.arg("--html-before-content")
|
||||
.arg(&version_info)
|
||||
.arg("--html-in-header")
|
||||
.arg(&header)
|
||||
.arg("--markdown-no-toc")
|
||||
.arg("--markdown-playground-url").arg("https://play.rust-lang.org/")
|
||||
.arg("-o").arg(&out).arg(&path)
|
||||
.arg("--markdown-css").arg("../rust.css");
|
||||
.arg("--markdown-playground-url")
|
||||
.arg("https://play.rust-lang.org/")
|
||||
.arg("-o")
|
||||
.arg(&out)
|
||||
.arg(&path)
|
||||
.arg("--markdown-css")
|
||||
.arg("../rust.css");
|
||||
|
||||
builder.run(&mut cmd);
|
||||
}
|
||||
|
@ -366,33 +355,39 @@ impl Step for Standalone {
|
|||
let path = file.path();
|
||||
let filename = path.file_name().unwrap().to_str().unwrap();
|
||||
if !filename.ends_with(".md") || filename == "README.md" {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
|
||||
let html = out.join(filename).with_extension("html");
|
||||
let rustdoc = builder.rustdoc(compiler);
|
||||
if up_to_date(&path, &html) &&
|
||||
up_to_date(&footer, &html) &&
|
||||
up_to_date(&favicon, &html) &&
|
||||
up_to_date(&full_toc, &html) &&
|
||||
(builder.config.dry_run || up_to_date(&version_info, &html)) &&
|
||||
(builder.config.dry_run || up_to_date(&rustdoc, &html)) {
|
||||
continue
|
||||
if up_to_date(&path, &html)
|
||||
&& up_to_date(&footer, &html)
|
||||
&& up_to_date(&favicon, &html)
|
||||
&& up_to_date(&full_toc, &html)
|
||||
&& (builder.config.dry_run || up_to_date(&version_info, &html))
|
||||
&& (builder.config.dry_run || up_to_date(&rustdoc, &html))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut cmd = builder.rustdoc_cmd(compiler);
|
||||
cmd.arg("--html-after-content").arg(&footer)
|
||||
.arg("--html-before-content").arg(&version_info)
|
||||
.arg("--html-in-header").arg(&favicon)
|
||||
.arg("--markdown-no-toc")
|
||||
.arg("--index-page").arg(&builder.src.join("src/doc/index.md"))
|
||||
.arg("--markdown-playground-url").arg("https://play.rust-lang.org/")
|
||||
.arg("-o").arg(&out)
|
||||
.arg(&path);
|
||||
cmd.arg("--html-after-content")
|
||||
.arg(&footer)
|
||||
.arg("--html-before-content")
|
||||
.arg(&version_info)
|
||||
.arg("--html-in-header")
|
||||
.arg(&favicon)
|
||||
.arg("--markdown-no-toc")
|
||||
.arg("--index-page")
|
||||
.arg(&builder.src.join("src/doc/index.md"))
|
||||
.arg("--markdown-playground-url")
|
||||
.arg("https://play.rust-lang.org/")
|
||||
.arg("-o")
|
||||
.arg(&out)
|
||||
.arg(&path);
|
||||
|
||||
if filename == "not_found.md" {
|
||||
cmd.arg("--markdown-css")
|
||||
.arg("https://doc.rust-lang.org/rust.css");
|
||||
cmd.arg("--markdown-css").arg("https://doc.rust-lang.org/rust.css");
|
||||
} else {
|
||||
cmd.arg("--markdown-css").arg("rust.css");
|
||||
}
|
||||
|
@ -417,10 +412,7 @@ impl Step for Std {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Std {
|
||||
stage: run.builder.top_stage,
|
||||
target: run.target
|
||||
});
|
||||
run.builder.ensure(Std { stage: run.builder.top_stage, target: run.target });
|
||||
}
|
||||
|
||||
/// Compile all standard library documentation.
|
||||
|
@ -436,8 +428,7 @@ impl Step for Std {
|
|||
let compiler = builder.compiler(stage, builder.config.build);
|
||||
|
||||
builder.ensure(compile::Std { compiler, target });
|
||||
let out_dir = builder.stage_out(compiler, Mode::Std)
|
||||
.join(target).join("doc");
|
||||
let out_dir = builder.stage_out(compiler, Mode::Std).join(target).join("doc");
|
||||
|
||||
// Here what we're doing is creating a *symlink* (directory junction on
|
||||
// Windows) to the final output location. This is not done as an
|
||||
|
@ -462,18 +453,21 @@ impl Step for Std {
|
|||
|
||||
// Keep a whitelist so we do not build internal stdlib crates, these will be
|
||||
// build by the rustc step later if enabled.
|
||||
cargo.arg("-Z").arg("unstable-options")
|
||||
.arg("-p").arg(package);
|
||||
cargo.arg("-Z").arg("unstable-options").arg("-p").arg(package);
|
||||
// Create all crate output directories first to make sure rustdoc uses
|
||||
// relative links.
|
||||
// FIXME: Cargo should probably do this itself.
|
||||
t!(fs::create_dir_all(out_dir.join(package)));
|
||||
cargo.arg("--")
|
||||
.arg("--markdown-css").arg("rust.css")
|
||||
.arg("--markdown-no-toc")
|
||||
.arg("--generate-redirect-pages")
|
||||
.arg("--resource-suffix").arg(crate::channel::CFG_RELEASE_NUM)
|
||||
.arg("--index-page").arg(&builder.src.join("src/doc/index.md"));
|
||||
cargo
|
||||
.arg("--")
|
||||
.arg("--markdown-css")
|
||||
.arg("rust.css")
|
||||
.arg("--markdown-no-toc")
|
||||
.arg("--generate-redirect-pages")
|
||||
.arg("--resource-suffix")
|
||||
.arg(crate::channel::CFG_RELEASE_NUM)
|
||||
.arg("--index-page")
|
||||
.arg(&builder.src.join("src/doc/index.md"));
|
||||
|
||||
builder.run(&mut cargo.into());
|
||||
};
|
||||
|
@ -501,10 +495,7 @@ impl Step for Rustc {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Rustc {
|
||||
stage: run.builder.top_stage,
|
||||
target: run.target,
|
||||
});
|
||||
run.builder.ensure(Rustc { stage: run.builder.top_stage, target: run.target });
|
||||
}
|
||||
|
||||
/// Generates compiler documentation.
|
||||
|
@ -568,7 +559,7 @@ impl Step for Rustc {
|
|||
fn find_compiler_crates(
|
||||
builder: &Builder<'_>,
|
||||
name: &Interned<String>,
|
||||
crates: &mut HashSet<Interned<String>>
|
||||
crates: &mut HashSet<Interned<String>>,
|
||||
) {
|
||||
// Add current crate.
|
||||
crates.insert(*name);
|
||||
|
@ -597,10 +588,7 @@ impl Step for Rustdoc {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Rustdoc {
|
||||
stage: run.builder.top_stage,
|
||||
target: run.target,
|
||||
});
|
||||
run.builder.ensure(Rustdoc { stage: run.builder.top_stage, target: run.target });
|
||||
}
|
||||
|
||||
/// Generates compiler documentation.
|
||||
|
@ -633,9 +621,7 @@ impl Step for Rustdoc {
|
|||
builder.ensure(tool::Rustdoc { compiler: compiler });
|
||||
|
||||
// Symlink compiler docs to the output directory of rustdoc documentation.
|
||||
let out_dir = builder.stage_out(compiler, Mode::ToolRustc)
|
||||
.join(target)
|
||||
.join("doc");
|
||||
let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target).join("doc");
|
||||
t!(fs::create_dir_all(&out_dir));
|
||||
t!(symlink_dir_force(&builder.config, &out, &out_dir));
|
||||
|
||||
|
@ -648,7 +634,7 @@ impl Step for Rustdoc {
|
|||
"doc",
|
||||
"src/tools/rustdoc",
|
||||
SourceType::InTree,
|
||||
&[]
|
||||
&[],
|
||||
);
|
||||
|
||||
// Only include compiler crates, no dependencies of those, such as `libc`.
|
||||
|
@ -676,9 +662,7 @@ impl Step for ErrorIndex {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(ErrorIndex {
|
||||
target: run.target,
|
||||
});
|
||||
run.builder.ensure(ErrorIndex { target: run.target });
|
||||
}
|
||||
|
||||
/// Generates the HTML rendered error-index by running the
|
||||
|
@ -690,10 +674,7 @@ impl Step for ErrorIndex {
|
|||
let out = builder.doc_out(target);
|
||||
t!(fs::create_dir_all(&out));
|
||||
let compiler = builder.compiler(2, builder.config.build);
|
||||
let mut index = tool::ErrorIndex::command(
|
||||
builder,
|
||||
compiler,
|
||||
);
|
||||
let mut index = tool::ErrorIndex::command(builder, compiler);
|
||||
index.arg("html");
|
||||
index.arg(out.join("error-index.html"));
|
||||
index.arg(crate::channel::CFG_RELEASE_NUM);
|
||||
|
@ -721,9 +702,7 @@ impl Step for UnstableBookGen {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(UnstableBookGen {
|
||||
target: run.target,
|
||||
});
|
||||
run.builder.ensure(UnstableBookGen { target: run.target });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
|
@ -751,9 +730,7 @@ fn symlink_dir_force(config: &Config, src: &Path, dst: &Path) -> io::Result<()>
|
|||
} else {
|
||||
// handle directory junctions on windows by falling back to
|
||||
// `remove_dir`.
|
||||
fs::remove_file(dst).or_else(|_| {
|
||||
fs::remove_dir(dst)
|
||||
})?;
|
||||
fs::remove_file(dst).or_else(|_| fs::remove_dir(dst))?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -88,16 +88,15 @@ pub enum Subcommand {
|
|||
|
||||
impl Default for Subcommand {
|
||||
fn default() -> Subcommand {
|
||||
Subcommand::Build {
|
||||
paths: vec![PathBuf::from("nowhere")],
|
||||
}
|
||||
Subcommand::Build { paths: vec![PathBuf::from("nowhere")] }
|
||||
}
|
||||
}
|
||||
|
||||
impl Flags {
|
||||
pub fn parse(args: &[String]) -> Flags {
|
||||
let mut extra_help = String::new();
|
||||
let mut subcommand_help = String::from("\
|
||||
let mut subcommand_help = String::from(
|
||||
"\
|
||||
Usage: x.py <subcommand> [options] [<paths>...]
|
||||
|
||||
Subcommands:
|
||||
|
@ -113,7 +112,7 @@ Subcommands:
|
|||
dist Build distribution artifacts
|
||||
install Install distribution artifacts
|
||||
|
||||
To learn more about a subcommand, run `./x.py <subcommand> -h`"
|
||||
To learn more about a subcommand, run `./x.py <subcommand> -h`",
|
||||
);
|
||||
|
||||
let mut opts = Options::new();
|
||||
|
@ -127,12 +126,20 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`"
|
|||
opts.optmulti("", "exclude", "build paths to exclude", "PATH");
|
||||
opts.optopt("", "on-fail", "command to run on failure", "CMD");
|
||||
opts.optflag("", "dry-run", "dry run; don't build anything");
|
||||
opts.optopt("", "stage",
|
||||
opts.optopt(
|
||||
"",
|
||||
"stage",
|
||||
"stage to build (indicates compiler to use/test, e.g., stage 0 uses the \
|
||||
bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)",
|
||||
"N");
|
||||
opts.optmulti("", "keep-stage", "stage(s) to keep without recompiling \
|
||||
(pass multiple times to keep e.g., both stages 0 and 1)", "N");
|
||||
"N",
|
||||
);
|
||||
opts.optmulti(
|
||||
"",
|
||||
"keep-stage",
|
||||
"stage(s) to keep without recompiling \
|
||||
(pass multiple times to keep e.g., both stages 0 and 1)",
|
||||
"N",
|
||||
);
|
||||
opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
|
||||
opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS");
|
||||
opts.optflag("h", "help", "print this help message");
|
||||
|
@ -197,11 +204,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`"
|
|||
);
|
||||
opts.optflag("", "no-doc", "do not run doc tests");
|
||||
opts.optflag("", "doc", "only run doc tests");
|
||||
opts.optflag(
|
||||
"",
|
||||
"bless",
|
||||
"update all stderr/stdout files of failing ui tests",
|
||||
);
|
||||
opts.optflag("", "bless", "update all stderr/stdout files of failing ui tests");
|
||||
opts.optopt(
|
||||
"",
|
||||
"compare-mode",
|
||||
|
@ -212,7 +215,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`"
|
|||
"",
|
||||
"pass",
|
||||
"force {check,build,run}-pass tests to this mode.",
|
||||
"check | build | run"
|
||||
"check | build | run",
|
||||
);
|
||||
opts.optflag(
|
||||
"",
|
||||
|
@ -386,10 +389,7 @@ Arguments:
|
|||
_ => {}
|
||||
};
|
||||
// Get any optional paths which occur after the subcommand
|
||||
let paths = matches.free[1..]
|
||||
.iter()
|
||||
.map(|p| p.into())
|
||||
.collect::<Vec<PathBuf>>();
|
||||
let paths = matches.free[1..].iter().map(|p| p.into()).collect::<Vec<PathBuf>>();
|
||||
|
||||
let cfg_file = matches.opt_str("config").map(PathBuf::from).or_else(|| {
|
||||
if fs::metadata("config.toml").is_ok() {
|
||||
|
@ -409,10 +409,8 @@ Arguments:
|
|||
extra_help.push_str(maybe_rules_help.unwrap_or_default().as_str());
|
||||
} else if !(subcommand.as_str() == "clean" || subcommand.as_str() == "fmt") {
|
||||
extra_help.push_str(
|
||||
format!(
|
||||
"Run `./x.py {} -h -v` to see a list of available paths.",
|
||||
subcommand
|
||||
).as_str(),
|
||||
format!("Run `./x.py {} -h -v` to see a list of available paths.", subcommand)
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -443,10 +441,7 @@ Arguments:
|
|||
DocTests::Yes
|
||||
},
|
||||
},
|
||||
"bench" => Subcommand::Bench {
|
||||
paths,
|
||||
test_args: matches.opt_strs("test-args"),
|
||||
},
|
||||
"bench" => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") },
|
||||
"doc" => Subcommand::Doc { paths },
|
||||
"clean" => {
|
||||
if !paths.is_empty() {
|
||||
|
@ -454,15 +449,9 @@ Arguments:
|
|||
usage(1, &opts, &subcommand_help, &extra_help);
|
||||
}
|
||||
|
||||
Subcommand::Clean {
|
||||
all: matches.opt_present("all"),
|
||||
}
|
||||
}
|
||||
"fmt" => {
|
||||
Subcommand::Format {
|
||||
check: matches.opt_present("check"),
|
||||
}
|
||||
Subcommand::Clean { all: matches.opt_present("all") }
|
||||
}
|
||||
"fmt" => Subcommand::Format { check: matches.opt_present("check") },
|
||||
"dist" => Subcommand::Dist { paths },
|
||||
"install" => Subcommand::Install { paths },
|
||||
_ => {
|
||||
|
@ -476,8 +465,10 @@ Arguments:
|
|||
dry_run: matches.opt_present("dry-run"),
|
||||
on_fail: matches.opt_str("on-fail"),
|
||||
rustc_error_format: matches.opt_str("error-format"),
|
||||
keep_stage: matches.opt_strs("keep-stage")
|
||||
.into_iter().map(|j| j.parse().expect("`keep-stage` should be a number"))
|
||||
keep_stage: matches
|
||||
.opt_strs("keep-stage")
|
||||
.into_iter()
|
||||
.map(|j| j.parse().expect("`keep-stage` should be a number"))
|
||||
.collect(),
|
||||
host: split(&matches.opt_strs("host"))
|
||||
.into_iter()
|
||||
|
@ -504,10 +495,7 @@ impl Subcommand {
|
|||
pub fn test_args(&self) -> Vec<&str> {
|
||||
match *self {
|
||||
Subcommand::Test { ref test_args, .. } | Subcommand::Bench { ref test_args, .. } => {
|
||||
test_args
|
||||
.iter()
|
||||
.flat_map(|s| s.split_whitespace())
|
||||
.collect()
|
||||
test_args.iter().flat_map(|s| s.split_whitespace()).collect()
|
||||
}
|
||||
_ => Vec::new(),
|
||||
}
|
||||
|
@ -515,10 +503,9 @@ impl Subcommand {
|
|||
|
||||
pub fn rustc_args(&self) -> Vec<&str> {
|
||||
match *self {
|
||||
Subcommand::Test { ref rustc_args, .. } => rustc_args
|
||||
.iter()
|
||||
.flat_map(|s| s.split_whitespace())
|
||||
.collect(),
|
||||
Subcommand::Test { ref rustc_args, .. } => {
|
||||
rustc_args.iter().flat_map(|s| s.split_whitespace()).collect()
|
||||
}
|
||||
_ => Vec::new(),
|
||||
}
|
||||
}
|
||||
|
@ -553,28 +540,21 @@ impl Subcommand {
|
|||
|
||||
pub fn compare_mode(&self) -> Option<&str> {
|
||||
match *self {
|
||||
Subcommand::Test {
|
||||
ref compare_mode, ..
|
||||
} => compare_mode.as_ref().map(|s| &s[..]),
|
||||
Subcommand::Test { ref compare_mode, .. } => compare_mode.as_ref().map(|s| &s[..]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pass(&self) -> Option<&str> {
|
||||
match *self {
|
||||
Subcommand::Test {
|
||||
ref pass, ..
|
||||
} => pass.as_ref().map(|s| &s[..]),
|
||||
Subcommand::Test { ref pass, .. } => pass.as_ref().map(|s| &s[..]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn split(s: &[String]) -> Vec<String> {
|
||||
s.iter()
|
||||
.flat_map(|s| s.split(','))
|
||||
.map(|s| s.to_string())
|
||||
.collect()
|
||||
s.iter().flat_map(|s| s.split(',')).map(|s| s.to_string()).collect()
|
||||
}
|
||||
|
||||
fn parse_deny_warnings(matches: &getopts::Matches) -> Option<bool> {
|
||||
|
@ -582,12 +562,9 @@ fn parse_deny_warnings(matches: &getopts::Matches) -> Option<bool> {
|
|||
Some("deny") => Some(true),
|
||||
Some("warn") => Some(false),
|
||||
Some(value) => {
|
||||
eprintln!(
|
||||
r#"invalid value for --warnings: {:?}, expected "warn" or "deny""#,
|
||||
value,
|
||||
);
|
||||
eprintln!(r#"invalid value for --warnings: {:?}, expected "warn" or "deny""#, value,);
|
||||
process::exit(1);
|
||||
},
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,11 @@
|
|||
|
||||
#![allow(nonstandard_style, dead_code)]
|
||||
|
||||
use crate::Build;
|
||||
use std::env;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use crate::Build;
|
||||
|
||||
type HANDLE = *mut u8;
|
||||
type BOOL = i32;
|
||||
|
@ -61,21 +61,23 @@ extern "system" {
|
|||
fn CreateJobObjectW(lpJobAttributes: *mut u8, lpName: *const u8) -> HANDLE;
|
||||
fn CloseHandle(hObject: HANDLE) -> BOOL;
|
||||
fn GetCurrentProcess() -> HANDLE;
|
||||
fn OpenProcess(dwDesiredAccess: DWORD,
|
||||
bInheritHandle: BOOL,
|
||||
dwProcessId: DWORD) -> HANDLE;
|
||||
fn DuplicateHandle(hSourceProcessHandle: HANDLE,
|
||||
hSourceHandle: HANDLE,
|
||||
hTargetProcessHandle: HANDLE,
|
||||
lpTargetHandle: LPHANDLE,
|
||||
dwDesiredAccess: DWORD,
|
||||
bInheritHandle: BOOL,
|
||||
dwOptions: DWORD) -> BOOL;
|
||||
fn OpenProcess(dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwProcessId: DWORD) -> HANDLE;
|
||||
fn DuplicateHandle(
|
||||
hSourceProcessHandle: HANDLE,
|
||||
hSourceHandle: HANDLE,
|
||||
hTargetProcessHandle: HANDLE,
|
||||
lpTargetHandle: LPHANDLE,
|
||||
dwDesiredAccess: DWORD,
|
||||
bInheritHandle: BOOL,
|
||||
dwOptions: DWORD,
|
||||
) -> BOOL;
|
||||
fn AssignProcessToJobObject(hJob: HANDLE, hProcess: HANDLE) -> BOOL;
|
||||
fn SetInformationJobObject(hJob: HANDLE,
|
||||
JobObjectInformationClass: JOBOBJECTINFOCLASS,
|
||||
lpJobObjectInformation: LPVOID,
|
||||
cbJobObjectInformationLength: DWORD) -> BOOL;
|
||||
fn SetInformationJobObject(
|
||||
hJob: HANDLE,
|
||||
JobObjectInformationClass: JOBOBJECTINFOCLASS,
|
||||
lpJobObjectInformation: LPVOID,
|
||||
cbJobObjectInformationLength: DWORD,
|
||||
) -> BOOL;
|
||||
fn SetErrorMode(mode: UINT) -> UINT;
|
||||
}
|
||||
|
||||
|
@ -132,10 +134,12 @@ pub unsafe fn setup(build: &mut Build) {
|
|||
info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PRIORITY_CLASS;
|
||||
info.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS;
|
||||
}
|
||||
let r = SetInformationJobObject(job,
|
||||
JobObjectExtendedLimitInformation,
|
||||
&mut info as *mut _ as LPVOID,
|
||||
mem::size_of_val(&info) as DWORD);
|
||||
let r = SetInformationJobObject(
|
||||
job,
|
||||
JobObjectExtendedLimitInformation,
|
||||
&mut info as *mut _ as LPVOID,
|
||||
mem::size_of_val(&info) as DWORD,
|
||||
);
|
||||
assert!(r != 0, "{}", io::Error::last_os_error());
|
||||
|
||||
// Assign our process to this job object. Note that if this fails, one very
|
||||
|
@ -150,7 +154,7 @@ pub unsafe fn setup(build: &mut Build) {
|
|||
let r = AssignProcessToJobObject(job, GetCurrentProcess());
|
||||
if r == 0 {
|
||||
CloseHandle(job);
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
// If we've got a parent process (e.g., the python script that called us)
|
||||
|
@ -169,9 +173,15 @@ pub unsafe fn setup(build: &mut Build) {
|
|||
let parent = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid.parse().unwrap());
|
||||
assert!(!parent.is_null(), "{}", io::Error::last_os_error());
|
||||
let mut parent_handle = ptr::null_mut();
|
||||
let r = DuplicateHandle(GetCurrentProcess(), job,
|
||||
parent, &mut parent_handle,
|
||||
0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
let r = DuplicateHandle(
|
||||
GetCurrentProcess(),
|
||||
job,
|
||||
parent,
|
||||
&mut parent_handle,
|
||||
0,
|
||||
FALSE,
|
||||
DUPLICATE_SAME_ACCESS,
|
||||
);
|
||||
|
||||
// If this failed, well at least we tried! An example of DuplicateHandle
|
||||
// failing in the past has been when the wrong python2 package spawned this
|
||||
|
|
|
@ -106,12 +106,12 @@
|
|||
#![feature(core_intrinsics)]
|
||||
#![feature(drain_filter)]
|
||||
|
||||
use std::cell::{RefCell, Cell};
|
||||
use std::collections::{HashSet, HashMap};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::env;
|
||||
use std::fs::{self, OpenOptions, File};
|
||||
use std::io::{Seek, SeekFrom, Write, Read};
|
||||
use std::path::{PathBuf, Path};
|
||||
use std::fs::{self, File, OpenOptions};
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{self, Command};
|
||||
use std::slice;
|
||||
use std::str;
|
||||
|
@ -121,33 +121,31 @@ use std::os::unix::fs::symlink as symlink_file;
|
|||
#[cfg(windows)]
|
||||
use std::os::windows::fs::symlink_file;
|
||||
|
||||
use build_helper::{
|
||||
mtime, output, run, run_suppressed, t, try_run, try_run_suppressed,
|
||||
};
|
||||
use build_helper::{mtime, output, run, run_suppressed, t, try_run, try_run_suppressed};
|
||||
use filetime::FileTime;
|
||||
|
||||
use crate::util::{exe, libdir, CiEnv};
|
||||
|
||||
mod builder;
|
||||
mod cache;
|
||||
mod cc_detect;
|
||||
mod channel;
|
||||
mod check;
|
||||
mod test;
|
||||
mod clean;
|
||||
mod compile;
|
||||
mod metadata;
|
||||
mod config;
|
||||
mod dist;
|
||||
mod doc;
|
||||
mod flags;
|
||||
mod format;
|
||||
mod install;
|
||||
mod metadata;
|
||||
mod native;
|
||||
mod sanity;
|
||||
pub mod util;
|
||||
mod builder;
|
||||
mod cache;
|
||||
mod test;
|
||||
mod tool;
|
||||
mod toolstate;
|
||||
mod format;
|
||||
pub mod util;
|
||||
|
||||
#[cfg(windows)]
|
||||
mod job;
|
||||
|
@ -163,13 +161,12 @@ mod job {
|
|||
|
||||
#[cfg(any(target_os = "haiku", target_os = "hermit", not(any(unix, windows))))]
|
||||
mod job {
|
||||
pub unsafe fn setup(_build: &mut crate::Build) {
|
||||
}
|
||||
pub unsafe fn setup(_build: &mut crate::Build) {}
|
||||
}
|
||||
|
||||
use crate::cache::{Interned, INTERNER};
|
||||
pub use crate::config::Config;
|
||||
use crate::flags::Subcommand;
|
||||
use crate::cache::{Interned, INTERNER};
|
||||
|
||||
const LLVM_TOOLS: &[&str] = &[
|
||||
"llvm-nm", // used to inspect binaries; it shows symbol names, their sizes and visibility
|
||||
|
@ -179,7 +176,7 @@ const LLVM_TOOLS: &[&str] = &[
|
|||
"llvm-readobj", // used to get information from ELFs/objects that the other tools don't provide
|
||||
"llvm-size", // used to prints the size of the linker sections of a program
|
||||
"llvm-strip", // used to discard symbols from binary files to reduce their size
|
||||
"llvm-ar" // used for creating and modifying archive files
|
||||
"llvm-ar", // used for creating and modifying archive files
|
||||
];
|
||||
|
||||
/// A structure representing a Rust compiler.
|
||||
|
@ -258,10 +255,8 @@ pub struct Build {
|
|||
ci_env: CiEnv,
|
||||
delayed_failures: RefCell<Vec<String>>,
|
||||
prerelease_version: Cell<Option<u32>>,
|
||||
tool_artifacts: RefCell<HashMap<
|
||||
Interned<String>,
|
||||
HashMap<String, (&'static str, PathBuf, Vec<String>)>
|
||||
>>,
|
||||
tool_artifacts:
|
||||
RefCell<HashMap<Interned<String>, HashMap<String, (&'static str, PathBuf, Vec<String>)>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -274,8 +269,7 @@ struct Crate {
|
|||
|
||||
impl Crate {
|
||||
fn is_local(&self, build: &Build) -> bool {
|
||||
self.path.starts_with(&build.config.src) &&
|
||||
!self.path.to_string_lossy().ends_with("_shim")
|
||||
self.path.starts_with(&build.config.src) && !self.path.to_string_lossy().ends_with("_shim")
|
||||
}
|
||||
|
||||
fn local_path(&self, build: &Build) -> PathBuf {
|
||||
|
@ -316,7 +310,7 @@ impl Mode {
|
|||
pub fn is_tool(&self) -> bool {
|
||||
match self {
|
||||
Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd => true,
|
||||
_ => false
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -331,12 +325,10 @@ impl Build {
|
|||
let out = config.out.clone();
|
||||
|
||||
let is_sudo = match env::var_os("SUDO_USER") {
|
||||
Some(sudo_user) => {
|
||||
match env::var_os("USER") {
|
||||
Some(user) => user != sudo_user,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
Some(sudo_user) => match env::var_os("USER") {
|
||||
Some(user) => user != sudo_user,
|
||||
None => false,
|
||||
},
|
||||
None => false,
|
||||
};
|
||||
|
||||
|
@ -393,11 +385,15 @@ impl Build {
|
|||
|
||||
// If local-rust is the same major.minor as the current version, then force a
|
||||
// local-rebuild
|
||||
let local_version_verbose = output(
|
||||
Command::new(&build.initial_rustc).arg("--version").arg("--verbose"));
|
||||
let local_version_verbose =
|
||||
output(Command::new(&build.initial_rustc).arg("--version").arg("--verbose"));
|
||||
let local_release = local_version_verbose
|
||||
.lines().filter(|x| x.starts_with("release:"))
|
||||
.next().unwrap().trim_start_matches("release:").trim();
|
||||
.lines()
|
||||
.filter(|x| x.starts_with("release:"))
|
||||
.next()
|
||||
.unwrap()
|
||||
.trim_start_matches("release:")
|
||||
.trim();
|
||||
let my_version = channel::CFG_RELEASE_NUM;
|
||||
if local_release.split('.').take(2).eq(my_version.split('.').take(2)) {
|
||||
build.verbose(&format!("auto-detected local-rebuild {}", local_release));
|
||||
|
@ -411,9 +407,7 @@ impl Build {
|
|||
}
|
||||
|
||||
pub fn build_triple(&self) -> &[Interned<String>] {
|
||||
unsafe {
|
||||
slice::from_raw_parts(&self.build, 1)
|
||||
}
|
||||
unsafe { slice::from_raw_parts(&self.build, 1) }
|
||||
}
|
||||
|
||||
/// Executes the entire build, as configured by the flags and configuration.
|
||||
|
@ -514,7 +508,7 @@ impl Build {
|
|||
/// Component directory that Cargo will produce output into (e.g.
|
||||
/// release/debug)
|
||||
fn cargo_dir(&self) -> &'static str {
|
||||
if self.config.rust_optimize {"release"} else {"debug"}
|
||||
if self.config.rust_optimize { "release" } else { "debug" }
|
||||
}
|
||||
|
||||
fn tools_dir(&self, compiler: Compiler) -> PathBuf {
|
||||
|
@ -535,17 +529,13 @@ impl Build {
|
|||
Mode::ToolBootstrap => "-bootstrap-tools",
|
||||
Mode::ToolStd | Mode::ToolRustc => "-tools",
|
||||
};
|
||||
self.out.join(&*compiler.host)
|
||||
.join(format!("stage{}{}", compiler.stage, suffix))
|
||||
self.out.join(&*compiler.host).join(format!("stage{}{}", compiler.stage, suffix))
|
||||
}
|
||||
|
||||
/// Returns the root output directory for all Cargo output in a given stage,
|
||||
/// running a particular compiler, whether or not we're building the
|
||||
/// standard library, and targeting the specified architecture.
|
||||
fn cargo_out(&self,
|
||||
compiler: Compiler,
|
||||
mode: Mode,
|
||||
target: Interned<String>) -> PathBuf {
|
||||
fn cargo_out(&self, compiler: Compiler, mode: Mode, target: Interned<String>) -> PathBuf {
|
||||
self.stage_out(compiler, mode).join(&*target).join(self.cargo_dir())
|
||||
}
|
||||
|
||||
|
@ -589,7 +579,7 @@ impl Build {
|
|||
fn is_rust_llvm(&self, target: Interned<String>) -> bool {
|
||||
match self.config.target_config.get(&target) {
|
||||
Some(ref c) => c.llvm_config.is_none(),
|
||||
None => true
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -607,8 +597,8 @@ impl Build {
|
|||
// On Fedora the system LLVM installs FileCheck in the
|
||||
// llvm subdirectory of the libdir.
|
||||
let llvm_libdir = output(Command::new(s).arg("--libdir"));
|
||||
let lib_filecheck = Path::new(llvm_libdir.trim())
|
||||
.join("llvm").join(exe("FileCheck", &*target));
|
||||
let lib_filecheck =
|
||||
Path::new(llvm_libdir.trim()).join("llvm").join(exe("FileCheck", &*target));
|
||||
if lib_filecheck.exists() {
|
||||
lib_filecheck
|
||||
} else {
|
||||
|
@ -667,14 +657,18 @@ impl Build {
|
|||
|
||||
/// Runs a command, printing out nice contextual information if it fails.
|
||||
fn run(&self, cmd: &mut Command) {
|
||||
if self.config.dry_run { return; }
|
||||
if self.config.dry_run {
|
||||
return;
|
||||
}
|
||||
self.verbose(&format!("running: {:?}", cmd));
|
||||
run(cmd)
|
||||
}
|
||||
|
||||
/// Runs a command, printing out nice contextual information if it fails.
|
||||
fn run_quiet(&self, cmd: &mut Command) {
|
||||
if self.config.dry_run { return; }
|
||||
if self.config.dry_run {
|
||||
return;
|
||||
}
|
||||
self.verbose(&format!("running: {:?}", cmd));
|
||||
run_suppressed(cmd)
|
||||
}
|
||||
|
@ -683,7 +677,9 @@ impl Build {
|
|||
/// Exits if the command failed to execute at all, otherwise returns its
|
||||
/// `status.success()`.
|
||||
fn try_run(&self, cmd: &mut Command) -> bool {
|
||||
if self.config.dry_run { return true; }
|
||||
if self.config.dry_run {
|
||||
return true;
|
||||
}
|
||||
self.verbose(&format!("running: {:?}", cmd));
|
||||
try_run(cmd)
|
||||
}
|
||||
|
@ -692,7 +688,9 @@ impl Build {
|
|||
/// Exits if the command failed to execute at all, otherwise returns its
|
||||
/// `status.success()`.
|
||||
fn try_run_quiet(&self, cmd: &mut Command) -> bool {
|
||||
if self.config.dry_run { return true; }
|
||||
if self.config.dry_run {
|
||||
return true;
|
||||
}
|
||||
self.verbose(&format!("running: {:?}", cmd));
|
||||
try_run_suppressed(cmd)
|
||||
}
|
||||
|
@ -720,7 +718,9 @@ impl Build {
|
|||
}
|
||||
|
||||
fn info(&self, msg: &str) {
|
||||
if self.config.dry_run { return; }
|
||||
if self.config.dry_run {
|
||||
return;
|
||||
}
|
||||
println!("{}", msg);
|
||||
}
|
||||
|
||||
|
@ -732,7 +732,7 @@ impl Build {
|
|||
|
||||
fn debuginfo_map(&self, which: GitRepo) -> Option<String> {
|
||||
if !self.config.rust_remap_debuginfo {
|
||||
return None
|
||||
return None;
|
||||
}
|
||||
|
||||
let path = match which {
|
||||
|
@ -755,10 +755,12 @@ impl Build {
|
|||
fn cflags(&self, target: Interned<String>, which: GitRepo) -> Vec<String> {
|
||||
// Filter out -O and /O (the optimization flags) that we picked up from
|
||||
// cc-rs because the build scripts will determine that for themselves.
|
||||
let mut base = self.cc[&target].args().iter()
|
||||
.map(|s| s.to_string_lossy().into_owned())
|
||||
.filter(|s| !s.starts_with("-O") && !s.starts_with("/O"))
|
||||
.collect::<Vec<String>>();
|
||||
let mut base = self.cc[&target]
|
||||
.args()
|
||||
.iter()
|
||||
.map(|s| s.to_string_lossy().into_owned())
|
||||
.filter(|s| !s.starts_with("-O") && !s.starts_with("/O"))
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
// If we're compiling on macOS then we add a few unconditional flags
|
||||
// indicating that we want libc++ (more filled out than libstdc++) and
|
||||
|
@ -776,7 +778,7 @@ impl Build {
|
|||
}
|
||||
|
||||
if let Some(map) = self.debuginfo_map(which) {
|
||||
let cc = self.cc(target);
|
||||
let cc = self.cc(target);
|
||||
if cc.ends_with("clang") || cc.ends_with("gcc") {
|
||||
base.push(format!("-fdebug-prefix-map={}", map));
|
||||
} else if cc.ends_with("clang-cl.exe") {
|
||||
|
@ -801,20 +803,21 @@ impl Build {
|
|||
fn cxx(&self, target: Interned<String>) -> Result<&Path, String> {
|
||||
match self.cxx.get(&target) {
|
||||
Some(p) => Ok(p.path()),
|
||||
None => Err(format!(
|
||||
"target `{}` is not configured as a host, only as a target",
|
||||
target))
|
||||
None => {
|
||||
Err(format!("target `{}` is not configured as a host, only as a target", target))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the path to the linker for the given target if it needs to be overridden.
|
||||
fn linker(&self, target: Interned<String>) -> Option<&Path> {
|
||||
if let Some(linker) = self.config.target_config.get(&target)
|
||||
.and_then(|c| c.linker.as_ref()) {
|
||||
if let Some(linker) = self.config.target_config.get(&target).and_then(|c| c.linker.as_ref())
|
||||
{
|
||||
Some(linker)
|
||||
} else if target != self.config.build &&
|
||||
util::use_host_linker(&target) &&
|
||||
!target.contains("msvc") {
|
||||
} else if target != self.config.build
|
||||
&& util::use_host_linker(&target)
|
||||
&& !target.contains("msvc")
|
||||
{
|
||||
Some(self.cc(target))
|
||||
} else {
|
||||
None
|
||||
|
@ -826,14 +829,15 @@ impl Build {
|
|||
if target.contains("pc-windows-msvc") {
|
||||
Some(true)
|
||||
} else {
|
||||
self.config.target_config.get(&target)
|
||||
.and_then(|t| t.crt_static)
|
||||
self.config.target_config.get(&target).and_then(|t| t.crt_static)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the "musl root" for this `target`, if defined
|
||||
fn musl_root(&self, target: Interned<String>) -> Option<&Path> {
|
||||
self.config.target_config.get(&target)
|
||||
self.config
|
||||
.target_config
|
||||
.get(&target)
|
||||
.and_then(|t| t.musl_root.as_ref())
|
||||
.or(self.config.musl_root.as_ref())
|
||||
.map(|p| &**p)
|
||||
|
@ -841,22 +845,20 @@ impl Build {
|
|||
|
||||
/// Returns the sysroot for the wasi target, if defined
|
||||
fn wasi_root(&self, target: Interned<String>) -> Option<&Path> {
|
||||
self.config.target_config.get(&target)
|
||||
.and_then(|t| t.wasi_root.as_ref())
|
||||
.map(|p| &**p)
|
||||
self.config.target_config.get(&target).and_then(|t| t.wasi_root.as_ref()).map(|p| &**p)
|
||||
}
|
||||
|
||||
/// Returns `true` if this is a no-std `target`, if defined
|
||||
fn no_std(&self, target: Interned<String>) -> Option<bool> {
|
||||
self.config.target_config.get(&target)
|
||||
.map(|t| t.no_std)
|
||||
self.config.target_config.get(&target).map(|t| t.no_std)
|
||||
}
|
||||
|
||||
/// Returns `true` if the target will be tested using the `remote-test-client`
|
||||
/// and `remote-test-server` binaries.
|
||||
fn remote_tested(&self, target: Interned<String>) -> bool {
|
||||
self.qemu_rootfs(target).is_some() || target.contains("android") ||
|
||||
env::var_os("TEST_DEVICE_ADDR").is_some()
|
||||
self.qemu_rootfs(target).is_some()
|
||||
|| target.contains("android")
|
||||
|| env::var_os("TEST_DEVICE_ADDR").is_some()
|
||||
}
|
||||
|
||||
/// Returns the root of the "rootfs" image that this target will be using,
|
||||
|
@ -865,9 +867,7 @@ impl Build {
|
|||
/// 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: Interned<String>) -> Option<&Path> {
|
||||
self.config.target_config.get(&target)
|
||||
.and_then(|t| t.qemu_rootfs.as_ref())
|
||||
.map(|p| &**p)
|
||||
self.config.target_config.get(&target).and_then(|t| t.qemu_rootfs.as_ref()).map(|p| &**p)
|
||||
}
|
||||
|
||||
/// Path to the python interpreter to use
|
||||
|
@ -899,9 +899,9 @@ impl Build {
|
|||
/// When all of these conditions are met the build will lift artifacts from
|
||||
/// the previous stage forward.
|
||||
fn force_use_stage1(&self, compiler: Compiler, target: Interned<String>) -> bool {
|
||||
!self.config.full_bootstrap &&
|
||||
compiler.stage >= 2 &&
|
||||
(self.hosts.iter().any(|h| *h == target) || target == self.build)
|
||||
!self.config.full_bootstrap
|
||||
&& compiler.stage >= 2
|
||||
&& (self.hosts.iter().any(|h| *h == target) || target == self.build)
|
||||
}
|
||||
|
||||
/// Given `num` in the form "a.b.c" return a "release string" which
|
||||
|
@ -912,11 +912,13 @@ impl Build {
|
|||
fn release(&self, num: &str) -> String {
|
||||
match &self.config.channel[..] {
|
||||
"stable" => num.to_string(),
|
||||
"beta" => if self.rust_info.is_git() {
|
||||
format!("{}-beta.{}", num, self.beta_prerelease_version())
|
||||
} else {
|
||||
format!("{}-beta", num)
|
||||
},
|
||||
"beta" => {
|
||||
if self.rust_info.is_git() {
|
||||
format!("{}-beta.{}", num, self.beta_prerelease_version())
|
||||
} else {
|
||||
format!("{}-beta", num)
|
||||
}
|
||||
}
|
||||
"nightly" => format!("{}-nightly", num),
|
||||
_ => format!("{}-dev", num),
|
||||
}
|
||||
|
@ -924,33 +926,21 @@ impl Build {
|
|||
|
||||
fn beta_prerelease_version(&self) -> u32 {
|
||||
if let Some(s) = self.prerelease_version.get() {
|
||||
return s
|
||||
return s;
|
||||
}
|
||||
|
||||
let beta = output(
|
||||
Command::new("git")
|
||||
.arg("ls-remote")
|
||||
.arg("origin")
|
||||
.arg("beta")
|
||||
.current_dir(&self.src)
|
||||
Command::new("git").arg("ls-remote").arg("origin").arg("beta").current_dir(&self.src),
|
||||
);
|
||||
let beta = beta.trim().split_whitespace().next().unwrap();
|
||||
let master = output(
|
||||
Command::new("git")
|
||||
.arg("ls-remote")
|
||||
.arg("origin")
|
||||
.arg("master")
|
||||
.current_dir(&self.src)
|
||||
Command::new("git").arg("ls-remote").arg("origin").arg("master").current_dir(&self.src),
|
||||
);
|
||||
let master = master.trim().split_whitespace().next().unwrap();
|
||||
|
||||
// Figure out where the current beta branch started.
|
||||
let base = output(
|
||||
Command::new("git")
|
||||
.arg("merge-base")
|
||||
.arg(beta)
|
||||
.arg(master)
|
||||
.current_dir(&self.src),
|
||||
Command::new("git").arg("merge-base").arg(beta).arg(master).current_dir(&self.src),
|
||||
);
|
||||
let base = base.trim();
|
||||
|
||||
|
@ -1061,7 +1051,7 @@ impl Build {
|
|||
let prefix = "version = \"";
|
||||
let suffix = "\"";
|
||||
if line.starts_with(prefix) && line.ends_with(suffix) {
|
||||
return line[prefix.len()..line.len() - suffix.len()].to_string()
|
||||
return line[prefix.len()..line.len() - suffix.len()].to_string();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1106,7 +1096,7 @@ impl Build {
|
|||
// run_cargo for more information (in compile.rs).
|
||||
for part in contents.split(|b| *b == 0) {
|
||||
if part.is_empty() {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
let host = part[0] as char == 'h';
|
||||
let path = PathBuf::from(t!(str::from_utf8(&part[1..])));
|
||||
|
@ -1117,9 +1107,13 @@ impl Build {
|
|||
|
||||
/// Copies a file from `src` to `dst`
|
||||
pub fn copy(&self, src: &Path, dst: &Path) {
|
||||
if self.config.dry_run { return; }
|
||||
if self.config.dry_run {
|
||||
return;
|
||||
}
|
||||
self.verbose_than(1, &format!("Copy {:?} to {:?}", src, dst));
|
||||
if src == dst { return; }
|
||||
if src == dst {
|
||||
return;
|
||||
}
|
||||
let _ = fs::remove_file(&dst);
|
||||
let metadata = t!(src.symlink_metadata());
|
||||
if metadata.file_type().is_symlink() {
|
||||
|
@ -1131,8 +1125,7 @@ impl Build {
|
|||
// just fall back to a slow `copy` operation.
|
||||
} else {
|
||||
if let Err(e) = fs::copy(src, dst) {
|
||||
panic!("failed to copy `{}` to `{}`: {}", src.display(),
|
||||
dst.display(), e)
|
||||
panic!("failed to copy `{}` to `{}`: {}", src.display(), dst.display(), e)
|
||||
}
|
||||
t!(fs::set_permissions(dst, metadata.permissions()));
|
||||
let atime = FileTime::from_last_access_time(&metadata);
|
||||
|
@ -1144,7 +1137,9 @@ impl Build {
|
|||
/// Search-and-replaces within a file. (Not maximally efficiently: allocates a
|
||||
/// new string for each replacement.)
|
||||
pub fn replace_in_file(&self, path: &Path, replacements: &[(&str, &str)]) {
|
||||
if self.config.dry_run { return; }
|
||||
if self.config.dry_run {
|
||||
return;
|
||||
}
|
||||
let mut contents = String::new();
|
||||
let mut file = t!(OpenOptions::new().read(true).write(true).open(path));
|
||||
t!(file.read_to_string(&mut contents));
|
||||
|
@ -1159,7 +1154,9 @@ impl Build {
|
|||
/// Copies the `src` directory recursively to `dst`. Both are assumed to exist
|
||||
/// when this function is called.
|
||||
pub fn cp_r(&self, src: &Path, dst: &Path) {
|
||||
if self.config.dry_run { return; }
|
||||
if self.config.dry_run {
|
||||
return;
|
||||
}
|
||||
for f in self.read_dir(src) {
|
||||
let path = f.path();
|
||||
let name = path.file_name().unwrap();
|
||||
|
@ -1210,7 +1207,9 @@ impl Build {
|
|||
}
|
||||
|
||||
fn install(&self, src: &Path, dstdir: &Path, perms: u32) {
|
||||
if self.config.dry_run { return; }
|
||||
if self.config.dry_run {
|
||||
return;
|
||||
}
|
||||
let dst = dstdir.join(src.file_name().unwrap());
|
||||
self.verbose_than(1, &format!("Install {:?} to {:?}", src, dst));
|
||||
t!(fs::create_dir_all(dstdir));
|
||||
|
@ -1221,8 +1220,7 @@ impl Build {
|
|||
}
|
||||
let metadata = t!(src.symlink_metadata());
|
||||
if let Err(e) = fs::copy(&src, &dst) {
|
||||
panic!("failed to copy `{}` to `{}`: {}", src.display(),
|
||||
dst.display(), e)
|
||||
panic!("failed to copy `{}` to `{}`: {}", src.display(), dst.display(), e)
|
||||
}
|
||||
t!(fs::set_permissions(&dst, metadata.permissions()));
|
||||
let atime = FileTime::from_last_access_time(&metadata);
|
||||
|
@ -1233,26 +1231,34 @@ impl Build {
|
|||
}
|
||||
|
||||
fn create(&self, path: &Path, s: &str) {
|
||||
if self.config.dry_run { return; }
|
||||
if self.config.dry_run {
|
||||
return;
|
||||
}
|
||||
t!(fs::write(path, s));
|
||||
}
|
||||
|
||||
fn read(&self, path: &Path) -> String {
|
||||
if self.config.dry_run { return String::new(); }
|
||||
if self.config.dry_run {
|
||||
return String::new();
|
||||
}
|
||||
t!(fs::read_to_string(path))
|
||||
}
|
||||
|
||||
fn create_dir(&self, dir: &Path) {
|
||||
if self.config.dry_run { return; }
|
||||
if self.config.dry_run {
|
||||
return;
|
||||
}
|
||||
t!(fs::create_dir_all(dir))
|
||||
}
|
||||
|
||||
fn remove_dir(&self, dir: &Path) {
|
||||
if self.config.dry_run { return; }
|
||||
if self.config.dry_run {
|
||||
return;
|
||||
}
|
||||
t!(fs::remove_dir_all(dir))
|
||||
}
|
||||
|
||||
fn read_dir(&self, dir: &Path) -> impl Iterator<Item=fs::DirEntry> {
|
||||
fn read_dir(&self, dir: &Path) -> impl Iterator<Item = fs::DirEntry> {
|
||||
let iter = match fs::read_dir(dir) {
|
||||
Ok(v) => v,
|
||||
Err(_) if self.config.dry_run => return vec![].into_iter(),
|
||||
|
@ -1262,7 +1268,9 @@ impl Build {
|
|||
}
|
||||
|
||||
fn remove(&self, f: &Path) {
|
||||
if self.config.dry_run { return; }
|
||||
if self.config.dry_run {
|
||||
return;
|
||||
}
|
||||
fs::remove_file(f).unwrap_or_else(|_| panic!("failed to remove {:?}", f));
|
||||
}
|
||||
}
|
||||
|
@ -1275,7 +1283,6 @@ fn chmod(path: &Path, perms: u32) {
|
|||
#[cfg(windows)]
|
||||
fn chmod(_path: &Path, _perms: u32) {}
|
||||
|
||||
|
||||
impl Compiler {
|
||||
pub fn with_stage(mut self, stage: u32) -> Compiler {
|
||||
self.stage = stage;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use std::collections::HashMap;
|
||||
use std::process::Command;
|
||||
use std::path::PathBuf;
|
||||
use std::collections::HashSet;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
use build_helper::output;
|
||||
use serde::Deserialize;
|
||||
use serde_json;
|
||||
|
||||
use crate::{Build, Crate};
|
||||
use crate::cache::INTERNER;
|
||||
use crate::{Build, Crate};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Output {
|
||||
|
@ -71,10 +71,14 @@ fn build_krate(features: &str, build: &mut Build, resolves: &mut Vec<ResolveNode
|
|||
// to know what crates to test. Here we run `cargo metadata` to learn about
|
||||
// the dependency graph and what `-p` arguments there are.
|
||||
let mut cargo = Command::new(&build.initial_cargo);
|
||||
cargo.arg("metadata")
|
||||
.arg("--format-version").arg("1")
|
||||
.arg("--features").arg(features)
|
||||
.arg("--manifest-path").arg(build.src.join(krate).join("Cargo.toml"));
|
||||
cargo
|
||||
.arg("metadata")
|
||||
.arg("--format-version")
|
||||
.arg("1")
|
||||
.arg("--features")
|
||||
.arg(features)
|
||||
.arg("--manifest-path")
|
||||
.arg(build.src.join(krate).join("Cargo.toml"));
|
||||
let output = output(&mut cargo);
|
||||
let output: Output = serde_json::from_str(&output).unwrap();
|
||||
for package in output.packages {
|
||||
|
@ -82,12 +86,7 @@ fn build_krate(features: &str, build: &mut Build, resolves: &mut Vec<ResolveNode
|
|||
let name = INTERNER.intern_string(package.name);
|
||||
let mut path = PathBuf::from(package.manifest_path);
|
||||
path.pop();
|
||||
build.crates.insert(name, Crate {
|
||||
name,
|
||||
id: package.id,
|
||||
deps: HashSet::new(),
|
||||
path,
|
||||
});
|
||||
build.crates.insert(name, Crate { name, id: package.id, deps: HashSet::new(), path });
|
||||
}
|
||||
}
|
||||
resolves.extend(output.resolve.nodes);
|
||||
|
|
|
@ -15,15 +15,15 @@ use std::path::{Path, PathBuf};
|
|||
use std::process::Command;
|
||||
|
||||
use build_helper::{output, t};
|
||||
use cmake;
|
||||
use cc;
|
||||
use cmake;
|
||||
|
||||
use crate::channel;
|
||||
use crate::util::{self, exe};
|
||||
use build_helper::up_to_date;
|
||||
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
|
||||
use crate::cache::Interned;
|
||||
use crate::channel;
|
||||
use crate::util::{self, exe};
|
||||
use crate::GitRepo;
|
||||
use build_helper::up_to_date;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub struct Llvm {
|
||||
|
@ -36,15 +36,11 @@ impl Step for Llvm {
|
|||
const ONLY_HOSTS: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/llvm-project")
|
||||
.path("src/llvm-project/llvm")
|
||||
.path("src/llvm")
|
||||
run.path("src/llvm-project").path("src/llvm-project/llvm").path("src/llvm")
|
||||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Llvm {
|
||||
target: run.target,
|
||||
});
|
||||
run.builder.ensure(Llvm { target: run.target });
|
||||
}
|
||||
|
||||
/// Compile LLVM for `target`.
|
||||
|
@ -56,7 +52,7 @@ impl Step for Llvm {
|
|||
if let Some(config) = builder.config.target_config.get(&target) {
|
||||
if let Some(ref s) = config.llvm_config {
|
||||
check_llvm_version(builder, s);
|
||||
return s.to_path_buf()
|
||||
return s.to_path_buf();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,8 +65,8 @@ impl Step for Llvm {
|
|||
}
|
||||
llvm_config_ret_dir.push("bin");
|
||||
|
||||
let build_llvm_config = llvm_config_ret_dir
|
||||
.join(exe("llvm-config", &*builder.config.build));
|
||||
let build_llvm_config =
|
||||
llvm_config_ret_dir.join(exe("llvm-config", &*builder.config.build));
|
||||
let done_stamp = out_dir.join("llvm-finished-building");
|
||||
|
||||
if done_stamp.exists() {
|
||||
|
@ -112,8 +108,10 @@ impl Step for Llvm {
|
|||
// defaults!
|
||||
let llvm_targets = match &builder.config.llvm_targets {
|
||||
Some(s) => s,
|
||||
None => "AArch64;ARM;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;\
|
||||
Sparc;SystemZ;WebAssembly;X86",
|
||||
None => {
|
||||
"AArch64;ARM;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;\
|
||||
Sparc;SystemZ;WebAssembly;X86"
|
||||
}
|
||||
};
|
||||
|
||||
let llvm_exp_targets = match builder.config.llvm_experimental_targets {
|
||||
|
@ -121,31 +119,31 @@ impl Step for Llvm {
|
|||
None => "",
|
||||
};
|
||||
|
||||
let assertions = if builder.config.llvm_assertions {"ON"} else {"OFF"};
|
||||
let assertions = if builder.config.llvm_assertions { "ON" } else { "OFF" };
|
||||
|
||||
cfg.out_dir(&out_dir)
|
||||
.profile(profile)
|
||||
.define("LLVM_ENABLE_ASSERTIONS", assertions)
|
||||
.define("LLVM_TARGETS_TO_BUILD", llvm_targets)
|
||||
.define("LLVM_EXPERIMENTAL_TARGETS_TO_BUILD", llvm_exp_targets)
|
||||
.define("LLVM_INCLUDE_EXAMPLES", "OFF")
|
||||
.define("LLVM_INCLUDE_TESTS", "OFF")
|
||||
.define("LLVM_INCLUDE_DOCS", "OFF")
|
||||
.define("LLVM_INCLUDE_BENCHMARKS", "OFF")
|
||||
.define("LLVM_ENABLE_ZLIB", "OFF")
|
||||
.define("WITH_POLLY", "OFF")
|
||||
.define("LLVM_ENABLE_TERMINFO", "OFF")
|
||||
.define("LLVM_ENABLE_LIBEDIT", "OFF")
|
||||
.define("LLVM_ENABLE_BINDINGS", "OFF")
|
||||
.define("LLVM_ENABLE_Z3_SOLVER", "OFF")
|
||||
.define("LLVM_PARALLEL_COMPILE_JOBS", builder.jobs().to_string())
|
||||
.define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
|
||||
.define("LLVM_DEFAULT_TARGET_TRIPLE", target);
|
||||
.profile(profile)
|
||||
.define("LLVM_ENABLE_ASSERTIONS", assertions)
|
||||
.define("LLVM_TARGETS_TO_BUILD", llvm_targets)
|
||||
.define("LLVM_EXPERIMENTAL_TARGETS_TO_BUILD", llvm_exp_targets)
|
||||
.define("LLVM_INCLUDE_EXAMPLES", "OFF")
|
||||
.define("LLVM_INCLUDE_TESTS", "OFF")
|
||||
.define("LLVM_INCLUDE_DOCS", "OFF")
|
||||
.define("LLVM_INCLUDE_BENCHMARKS", "OFF")
|
||||
.define("LLVM_ENABLE_ZLIB", "OFF")
|
||||
.define("WITH_POLLY", "OFF")
|
||||
.define("LLVM_ENABLE_TERMINFO", "OFF")
|
||||
.define("LLVM_ENABLE_LIBEDIT", "OFF")
|
||||
.define("LLVM_ENABLE_BINDINGS", "OFF")
|
||||
.define("LLVM_ENABLE_Z3_SOLVER", "OFF")
|
||||
.define("LLVM_PARALLEL_COMPILE_JOBS", builder.jobs().to_string())
|
||||
.define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
|
||||
.define("LLVM_DEFAULT_TARGET_TRIPLE", target);
|
||||
|
||||
if builder.config.llvm_thin_lto {
|
||||
cfg.define("LLVM_ENABLE_LTO", "Thin");
|
||||
if !target.contains("apple") {
|
||||
cfg.define("LLVM_ENABLE_LLD", "ON");
|
||||
cfg.define("LLVM_ENABLE_LLD", "ON");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,20 +210,17 @@ impl Step for Llvm {
|
|||
|
||||
// http://llvm.org/docs/HowToCrossCompileLLVM.html
|
||||
if target != builder.config.build {
|
||||
builder.ensure(Llvm {
|
||||
target: builder.config.build,
|
||||
});
|
||||
builder.ensure(Llvm { target: builder.config.build });
|
||||
// FIXME: if the llvm root for the build triple is overridden then we
|
||||
// should use llvm-tblgen from there, also should verify that it
|
||||
// actually exists most of the time in normal installs of LLVM.
|
||||
let host = builder.llvm_out(builder.config.build).join("bin/llvm-tblgen");
|
||||
cfg.define("CMAKE_CROSSCOMPILING", "True")
|
||||
.define("LLVM_TABLEGEN", &host);
|
||||
cfg.define("CMAKE_CROSSCOMPILING", "True").define("LLVM_TABLEGEN", &host);
|
||||
|
||||
if target.contains("netbsd") {
|
||||
cfg.define("CMAKE_SYSTEM_NAME", "NetBSD");
|
||||
cfg.define("CMAKE_SYSTEM_NAME", "NetBSD");
|
||||
} else if target.contains("freebsd") {
|
||||
cfg.define("CMAKE_SYSTEM_NAME", "FreeBSD");
|
||||
cfg.define("CMAKE_SYSTEM_NAME", "FreeBSD");
|
||||
}
|
||||
|
||||
cfg.define("LLVM_NATIVE_BUILD", builder.llvm_out(builder.config.build).join("build"));
|
||||
|
@ -237,11 +232,8 @@ impl Step for Llvm {
|
|||
cfg.define("LLVM_VERSION_SUFFIX", suffix);
|
||||
}
|
||||
} else {
|
||||
let mut default_suffix = format!(
|
||||
"-rust-{}-{}",
|
||||
channel::CFG_RELEASE_NUM,
|
||||
builder.config.channel,
|
||||
);
|
||||
let mut default_suffix =
|
||||
format!("-rust-{}-{}", channel::CFG_RELEASE_NUM, builder.config.channel,);
|
||||
if let Some(sha) = llvm_info.sha_short() {
|
||||
default_suffix.push_str("-");
|
||||
default_suffix.push_str(sha);
|
||||
|
@ -282,7 +274,7 @@ impl Step for Llvm {
|
|||
|
||||
fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
|
||||
if !builder.config.llvm_version_check {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if builder.config.dry_run {
|
||||
|
@ -291,19 +283,16 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
|
|||
|
||||
let mut cmd = Command::new(llvm_config);
|
||||
let version = output(cmd.arg("--version"));
|
||||
let mut parts = version.split('.').take(2)
|
||||
.filter_map(|s| s.parse::<u32>().ok());
|
||||
let mut parts = version.split('.').take(2).filter_map(|s| s.parse::<u32>().ok());
|
||||
if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) {
|
||||
if major >= 7 {
|
||||
return
|
||||
return;
|
||||
}
|
||||
}
|
||||
panic!("\n\nbad LLVM version: {}, need >=7.0\n\n", version)
|
||||
}
|
||||
|
||||
fn configure_cmake(builder: &Builder<'_>,
|
||||
target: Interned<String>,
|
||||
cfg: &mut cmake::Config) {
|
||||
fn configure_cmake(builder: &Builder<'_>, target: Interned<String>, cfg: &mut cmake::Config) {
|
||||
// Do not print installation messages for up-to-date files.
|
||||
// LLVM and LLD builds can produce a lot of those and hit CI limits on log size.
|
||||
cfg.define("CMAKE_INSTALL_MESSAGE", "LAZY");
|
||||
|
@ -311,8 +300,7 @@ fn configure_cmake(builder: &Builder<'_>,
|
|||
if builder.config.ninja {
|
||||
cfg.generator("Ninja");
|
||||
}
|
||||
cfg.target(&target)
|
||||
.host(&builder.config.build);
|
||||
cfg.target(&target).host(&builder.config.build);
|
||||
|
||||
let sanitize_cc = |cc: &Path| {
|
||||
if target.contains("msvc") {
|
||||
|
@ -326,7 +314,7 @@ fn configure_cmake(builder: &Builder<'_>,
|
|||
// vars that we'd otherwise configure. In that case we just skip this
|
||||
// entirely.
|
||||
if target.contains("msvc") && !builder.config.ninja {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
let (cc, cxx) = match builder.config.llvm_clang_cl {
|
||||
|
@ -335,56 +323,52 @@ fn configure_cmake(builder: &Builder<'_>,
|
|||
};
|
||||
|
||||
// Handle msvc + ninja + ccache specially (this is what the bots use)
|
||||
if target.contains("msvc") &&
|
||||
builder.config.ninja &&
|
||||
builder.config.ccache.is_some()
|
||||
{
|
||||
let mut wrap_cc = env::current_exe().expect("failed to get cwd");
|
||||
wrap_cc.set_file_name("sccache-plus-cl.exe");
|
||||
if target.contains("msvc") && builder.config.ninja && builder.config.ccache.is_some() {
|
||||
let mut wrap_cc = env::current_exe().expect("failed to get cwd");
|
||||
wrap_cc.set_file_name("sccache-plus-cl.exe");
|
||||
|
||||
cfg.define("CMAKE_C_COMPILER", sanitize_cc(&wrap_cc))
|
||||
.define("CMAKE_CXX_COMPILER", sanitize_cc(&wrap_cc));
|
||||
cfg.env("SCCACHE_PATH",
|
||||
builder.config.ccache.as_ref().unwrap())
|
||||
.env("SCCACHE_TARGET", target)
|
||||
.env("SCCACHE_CC", &cc)
|
||||
.env("SCCACHE_CXX", &cxx);
|
||||
cfg.define("CMAKE_C_COMPILER", sanitize_cc(&wrap_cc))
|
||||
.define("CMAKE_CXX_COMPILER", sanitize_cc(&wrap_cc));
|
||||
cfg.env("SCCACHE_PATH", builder.config.ccache.as_ref().unwrap())
|
||||
.env("SCCACHE_TARGET", target)
|
||||
.env("SCCACHE_CC", &cc)
|
||||
.env("SCCACHE_CXX", &cxx);
|
||||
|
||||
// Building LLVM on MSVC can be a little ludicrous at times. We're so far
|
||||
// off the beaten path here that I'm not really sure this is even half
|
||||
// supported any more. Here we're trying to:
|
||||
//
|
||||
// * Build LLVM on MSVC
|
||||
// * Build LLVM with `clang-cl` instead of `cl.exe`
|
||||
// * Build a project with `sccache`
|
||||
// * Build for 32-bit as well
|
||||
// * Build with Ninja
|
||||
//
|
||||
// For `cl.exe` there are different binaries to compile 32/64 bit which
|
||||
// we use but for `clang-cl` there's only one which internally
|
||||
// multiplexes via flags. As a result it appears that CMake's detection
|
||||
// of a compiler's architecture and such on MSVC **doesn't** pass any
|
||||
// custom flags we pass in CMAKE_CXX_FLAGS below. This means that if we
|
||||
// use `clang-cl.exe` it's always diagnosed as a 64-bit compiler which
|
||||
// definitely causes problems since all the env vars are pointing to
|
||||
// 32-bit libraries.
|
||||
//
|
||||
// To hack around this... again... we pass an argument that's
|
||||
// unconditionally passed in the sccache shim. This'll get CMake to
|
||||
// correctly diagnose it's doing a 32-bit compilation and LLVM will
|
||||
// internally configure itself appropriately.
|
||||
if builder.config.llvm_clang_cl.is_some() && target.contains("i686") {
|
||||
cfg.env("SCCACHE_EXTRA_ARGS", "-m32");
|
||||
}
|
||||
// Building LLVM on MSVC can be a little ludicrous at times. We're so far
|
||||
// off the beaten path here that I'm not really sure this is even half
|
||||
// supported any more. Here we're trying to:
|
||||
//
|
||||
// * Build LLVM on MSVC
|
||||
// * Build LLVM with `clang-cl` instead of `cl.exe`
|
||||
// * Build a project with `sccache`
|
||||
// * Build for 32-bit as well
|
||||
// * Build with Ninja
|
||||
//
|
||||
// For `cl.exe` there are different binaries to compile 32/64 bit which
|
||||
// we use but for `clang-cl` there's only one which internally
|
||||
// multiplexes via flags. As a result it appears that CMake's detection
|
||||
// of a compiler's architecture and such on MSVC **doesn't** pass any
|
||||
// custom flags we pass in CMAKE_CXX_FLAGS below. This means that if we
|
||||
// use `clang-cl.exe` it's always diagnosed as a 64-bit compiler which
|
||||
// definitely causes problems since all the env vars are pointing to
|
||||
// 32-bit libraries.
|
||||
//
|
||||
// To hack around this... again... we pass an argument that's
|
||||
// unconditionally passed in the sccache shim. This'll get CMake to
|
||||
// correctly diagnose it's doing a 32-bit compilation and LLVM will
|
||||
// internally configure itself appropriately.
|
||||
if builder.config.llvm_clang_cl.is_some() && target.contains("i686") {
|
||||
cfg.env("SCCACHE_EXTRA_ARGS", "-m32");
|
||||
}
|
||||
} else {
|
||||
// If ccache is configured we inform the build a little differently how
|
||||
// to invoke ccache while also invoking our compilers.
|
||||
if let Some(ref ccache) = builder.config.ccache {
|
||||
cfg.define("CMAKE_C_COMPILER_LAUNCHER", ccache)
|
||||
.define("CMAKE_CXX_COMPILER_LAUNCHER", ccache);
|
||||
}
|
||||
cfg.define("CMAKE_C_COMPILER", sanitize_cc(cc))
|
||||
.define("CMAKE_CXX_COMPILER", sanitize_cc(cxx));
|
||||
// If ccache is configured we inform the build a little differently how
|
||||
// to invoke ccache while also invoking our compilers.
|
||||
if let Some(ref ccache) = builder.config.ccache {
|
||||
cfg.define("CMAKE_C_COMPILER_LAUNCHER", ccache)
|
||||
.define("CMAKE_CXX_COMPILER_LAUNCHER", ccache);
|
||||
}
|
||||
cfg.define("CMAKE_C_COMPILER", sanitize_cc(cc))
|
||||
.define("CMAKE_CXX_COMPILER", sanitize_cc(cxx));
|
||||
}
|
||||
|
||||
cfg.build_arg("-j").build_arg(builder.jobs().to_string());
|
||||
|
@ -394,10 +378,7 @@ fn configure_cmake(builder: &Builder<'_>,
|
|||
}
|
||||
cfg.define("CMAKE_C_FLAGS", cflags);
|
||||
let mut cxxflags = builder.cflags(target, GitRepo::Llvm).join(" ");
|
||||
if builder.config.llvm_static_stdcpp &&
|
||||
!target.contains("msvc") &&
|
||||
!target.contains("netbsd")
|
||||
{
|
||||
if builder.config.llvm_static_stdcpp && !target.contains("msvc") && !target.contains("netbsd") {
|
||||
cxxflags.push_str(" -static-libstdc++");
|
||||
}
|
||||
if let Some(ref s) = builder.config.llvm_cxxflags {
|
||||
|
@ -455,14 +436,12 @@ impl Step for Lld {
|
|||
}
|
||||
let target = self.target;
|
||||
|
||||
let llvm_config = builder.ensure(Llvm {
|
||||
target: self.target,
|
||||
});
|
||||
let llvm_config = builder.ensure(Llvm { target: self.target });
|
||||
|
||||
let out_dir = builder.lld_out(target);
|
||||
let done_stamp = out_dir.join("lld-finished-building");
|
||||
if done_stamp.exists() {
|
||||
return out_dir
|
||||
return out_dir;
|
||||
}
|
||||
|
||||
builder.info(&format!("Building LLD for {}", target));
|
||||
|
@ -486,14 +465,12 @@ impl Step for Lld {
|
|||
// ensure we don't hit the same bugs with escaping. It means that you
|
||||
// can't build on a system where your paths require `\` on Windows, but
|
||||
// there's probably a lot of reasons you can't do that other than this.
|
||||
let llvm_config_shim = env::current_exe()
|
||||
.unwrap()
|
||||
.with_file_name("llvm-config-wrapper");
|
||||
let llvm_config_shim = env::current_exe().unwrap().with_file_name("llvm-config-wrapper");
|
||||
cfg.out_dir(&out_dir)
|
||||
.profile("Release")
|
||||
.env("LLVM_CONFIG_REAL", llvm_config)
|
||||
.define("LLVM_CONFIG_PATH", llvm_config_shim)
|
||||
.define("LLVM_INCLUDE_TESTS", "OFF");
|
||||
.profile("Release")
|
||||
.env("LLVM_CONFIG_REAL", llvm_config)
|
||||
.define("LLVM_CONFIG_PATH", llvm_config_shim)
|
||||
.define("LLVM_INCLUDE_TESTS", "OFF");
|
||||
|
||||
cfg.build();
|
||||
|
||||
|
@ -528,7 +505,7 @@ impl Step for TestHelpers {
|
|||
let dst = builder.test_helpers_out(target);
|
||||
let src = builder.src.join("src/test/auxiliary/rust_test_helpers.c");
|
||||
if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
builder.info("Building test helpers");
|
||||
|
@ -550,13 +527,13 @@ impl Step for TestHelpers {
|
|||
}
|
||||
|
||||
cfg.cargo_metadata(false)
|
||||
.out_dir(&dst)
|
||||
.target(&target)
|
||||
.host(&builder.config.build)
|
||||
.opt_level(0)
|
||||
.warnings(false)
|
||||
.debug(false)
|
||||
.file(builder.src.join("src/test/auxiliary/rust_test_helpers.c"))
|
||||
.compile("rust_test_helpers");
|
||||
.out_dir(&dst)
|
||||
.target(&target)
|
||||
.host(&builder.config.build)
|
||||
.opt_level(0)
|
||||
.warnings(false)
|
||||
.debug(false)
|
||||
.file(builder.src.join("src/test/auxiliary/rust_test_helpers.c"))
|
||||
.compile("rust_test_helpers");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::ffi::{OsString, OsStr};
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
@ -26,30 +26,31 @@ struct Finder {
|
|||
|
||||
impl Finder {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
cache: HashMap::new(),
|
||||
path: env::var_os("PATH").unwrap_or_default()
|
||||
}
|
||||
Self { cache: HashMap::new(), path: env::var_os("PATH").unwrap_or_default() }
|
||||
}
|
||||
|
||||
fn maybe_have<S: AsRef<OsStr>>(&mut self, cmd: S) -> Option<PathBuf> {
|
||||
let cmd: OsString = cmd.as_ref().into();
|
||||
let path = &self.path;
|
||||
self.cache.entry(cmd.clone()).or_insert_with(|| {
|
||||
for path in env::split_paths(path) {
|
||||
let target = path.join(&cmd);
|
||||
let mut cmd_exe = cmd.clone();
|
||||
cmd_exe.push(".exe");
|
||||
self.cache
|
||||
.entry(cmd.clone())
|
||||
.or_insert_with(|| {
|
||||
for path in env::split_paths(path) {
|
||||
let target = path.join(&cmd);
|
||||
let mut cmd_exe = cmd.clone();
|
||||
cmd_exe.push(".exe");
|
||||
|
||||
if target.is_file() // some/path/git
|
||||
if target.is_file() // some/path/git
|
||||
|| path.join(&cmd_exe).exists() // some/path/git.exe
|
||||
|| target.join(&cmd_exe).exists() // some/path/git/git.exe
|
||||
{
|
||||
return Some(target);
|
||||
|| target.join(&cmd_exe).exists()
|
||||
// some/path/git/git.exe
|
||||
{
|
||||
return Some(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}).clone()
|
||||
None
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
|
||||
fn must_have<S: AsRef<OsStr>>(&mut self, cmd: S) -> PathBuf {
|
||||
|
@ -77,11 +78,17 @@ pub fn check(build: &mut Build) {
|
|||
}
|
||||
|
||||
// We need cmake, but only if we're actually building LLVM or sanitizers.
|
||||
let building_llvm = build.hosts.iter()
|
||||
.map(|host| build.config.target_config
|
||||
.get(host)
|
||||
.map(|config| config.llvm_config.is_none())
|
||||
.unwrap_or(true))
|
||||
let building_llvm = build
|
||||
.hosts
|
||||
.iter()
|
||||
.map(|host| {
|
||||
build
|
||||
.config
|
||||
.target_config
|
||||
.get(host)
|
||||
.map(|config| config.llvm_config.is_none())
|
||||
.unwrap_or(true)
|
||||
})
|
||||
.any(|build_llvm_ourselves| build_llvm_ourselves);
|
||||
if building_llvm || build.config.sanitizers {
|
||||
cmd_finder.must_have("cmake");
|
||||
|
@ -119,17 +126,29 @@ pub fn check(build: &mut Build) {
|
|||
}
|
||||
}
|
||||
|
||||
build.config.python = build.config.python.take().map(|p| cmd_finder.must_have(p))
|
||||
build.config.python = build
|
||||
.config
|
||||
.python
|
||||
.take()
|
||||
.map(|p| cmd_finder.must_have(p))
|
||||
.or_else(|| cmd_finder.maybe_have("python2.7"))
|
||||
.or_else(|| cmd_finder.maybe_have("python2"))
|
||||
.or_else(|| env::var_os("BOOTSTRAP_PYTHON").map(PathBuf::from)) // set by bootstrap.py
|
||||
.or_else(|| Some(cmd_finder.must_have("python")));
|
||||
|
||||
build.config.nodejs = build.config.nodejs.take().map(|p| cmd_finder.must_have(p))
|
||||
build.config.nodejs = build
|
||||
.config
|
||||
.nodejs
|
||||
.take()
|
||||
.map(|p| cmd_finder.must_have(p))
|
||||
.or_else(|| cmd_finder.maybe_have("node"))
|
||||
.or_else(|| cmd_finder.maybe_have("nodejs"));
|
||||
|
||||
build.config.gdb = build.config.gdb.take().map(|p| cmd_finder.must_have(p))
|
||||
build.config.gdb = build
|
||||
.config
|
||||
.gdb
|
||||
.take()
|
||||
.map(|p| cmd_finder.must_have(p))
|
||||
.or_else(|| cmd_finder.maybe_have("gdb"));
|
||||
|
||||
// We're gonna build some custom C code here and there, host triples
|
||||
|
@ -169,15 +188,13 @@ pub fn check(build: &mut Build) {
|
|||
|
||||
for target in &build.targets {
|
||||
// Can't compile for iOS unless we're on macOS
|
||||
if target.contains("apple-ios") &&
|
||||
!build.build.contains("apple-darwin") {
|
||||
if target.contains("apple-ios") && !build.build.contains("apple-darwin") {
|
||||
panic!("the iOS target is only supported on macOS");
|
||||
}
|
||||
|
||||
if target.contains("-none-") || target.contains("nvptx") {
|
||||
if build.no_std(*target).is_none() {
|
||||
let target = build.config.target_config.entry(target.clone())
|
||||
.or_default();
|
||||
let target = build.config.target_config.entry(target.clone()).or_default();
|
||||
|
||||
target.no_std = true;
|
||||
}
|
||||
|
@ -192,22 +209,20 @@ pub fn check(build: &mut Build) {
|
|||
// If this is a native target (host is also musl) and no musl-root is given,
|
||||
// fall back to the system toolchain in /usr before giving up
|
||||
if build.musl_root(*target).is_none() && build.config.build == *target {
|
||||
let target = build.config.target_config.entry(target.clone())
|
||||
.or_default();
|
||||
let target = build.config.target_config.entry(target.clone()).or_default();
|
||||
target.musl_root = Some("/usr".into());
|
||||
}
|
||||
match build.musl_root(*target) {
|
||||
Some(root) => {
|
||||
if fs::metadata(root.join("lib/libc.a")).is_err() {
|
||||
panic!("couldn't find libc.a in musl dir: {}",
|
||||
root.join("lib").display());
|
||||
panic!("couldn't find libc.a in musl dir: {}", root.join("lib").display());
|
||||
}
|
||||
}
|
||||
None => {
|
||||
panic!("when targeting MUSL either the rust.musl-root \
|
||||
None => panic!(
|
||||
"when targeting MUSL either the rust.musl-root \
|
||||
option or the target.$TARGET.musl-root option must \
|
||||
be specified in config.toml")
|
||||
}
|
||||
be specified in config.toml"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,7 +232,8 @@ pub fn check(build: &mut Build) {
|
|||
// Studio, so detect that here and error.
|
||||
let out = output(Command::new("cmake").arg("--help"));
|
||||
if !out.contains("Visual Studio") {
|
||||
panic!("
|
||||
panic!(
|
||||
"
|
||||
cmake does not support Visual Studio generators.
|
||||
|
||||
This is likely due to it being an msys/cygwin build of cmake,
|
||||
|
@ -228,7 +244,8 @@ If you are building under msys2 try installing the mingw-w64-x86_64-cmake
|
|||
package instead of cmake:
|
||||
|
||||
$ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
|
||||
");
|
||||
"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -240,8 +257,10 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
|
|||
if build.config.channel == "stable" {
|
||||
let stage0 = t!(fs::read_to_string(build.src.join("src/stage0.txt")));
|
||||
if stage0.contains("\ndev:") {
|
||||
panic!("bootstrapping from a dev compiler in a stable release, but \
|
||||
should only be bootstrapping from a released compiler!");
|
||||
panic!(
|
||||
"bootstrapping from a dev compiler in a stable release, but \
|
||||
should only be bootstrapping from a released compiler!"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,11 @@ use crate::compile;
|
|||
use crate::dist;
|
||||
use crate::flags::Subcommand;
|
||||
use crate::native;
|
||||
use crate::tool::{self, Tool, SourceType};
|
||||
use crate::tool::{self, SourceType, Tool};
|
||||
use crate::toolstate::ToolState;
|
||||
use crate::util::{self, dylib_path, dylib_path_var};
|
||||
use crate::Crate as CargoCrate;
|
||||
use crate::{DocTests, Mode, GitRepo, envify};
|
||||
use crate::{envify, DocTests, GitRepo, Mode};
|
||||
|
||||
const ADB_TEST_DIR: &str = "/data/tmp/work";
|
||||
|
||||
|
@ -115,16 +115,13 @@ impl Step for Linkcheck {
|
|||
let _time = util::timeit(&builder);
|
||||
try_run(
|
||||
builder,
|
||||
builder
|
||||
.tool_cmd(Tool::Linkchecker)
|
||||
.arg(builder.out.join(host).join("doc")),
|
||||
builder.tool_cmd(Tool::Linkchecker).arg(builder.out.join(host).join("doc")),
|
||||
);
|
||||
}
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
run.path("src/tools/linkchecker")
|
||||
.default_condition(builder.config.docs)
|
||||
run.path("src/tools/linkchecker").default_condition(builder.config.docs)
|
||||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
|
@ -147,10 +144,7 @@ impl Step for Cargotest {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Cargotest {
|
||||
stage: run.builder.top_stage,
|
||||
host: run.target,
|
||||
});
|
||||
run.builder.ensure(Cargotest { stage: run.builder.top_stage, host: run.target });
|
||||
}
|
||||
|
||||
/// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler.
|
||||
|
@ -159,10 +153,7 @@ impl Step for Cargotest {
|
|||
/// test` to ensure that we don't regress the test suites there.
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
let compiler = builder.compiler(self.stage, self.host);
|
||||
builder.ensure(compile::Rustc {
|
||||
compiler,
|
||||
target: compiler.host,
|
||||
});
|
||||
builder.ensure(compile::Rustc { compiler, target: compiler.host });
|
||||
|
||||
// Note that this is a short, cryptic, and not scoped directory name. This
|
||||
// is currently to minimize the length of path on Windows where we otherwise
|
||||
|
@ -197,28 +188,24 @@ impl Step for Cargo {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Cargo {
|
||||
stage: run.builder.top_stage,
|
||||
host: run.target,
|
||||
});
|
||||
run.builder.ensure(Cargo { stage: run.builder.top_stage, host: run.target });
|
||||
}
|
||||
|
||||
/// Runs `cargo test` for `cargo` packaged with Rust.
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
let compiler = builder.compiler(self.stage, self.host);
|
||||
|
||||
builder.ensure(tool::Cargo {
|
||||
builder.ensure(tool::Cargo { compiler, target: self.host });
|
||||
let mut cargo = tool::prepare_tool_cargo(
|
||||
builder,
|
||||
compiler,
|
||||
target: self.host,
|
||||
});
|
||||
let mut cargo = tool::prepare_tool_cargo(builder,
|
||||
compiler,
|
||||
Mode::ToolRustc,
|
||||
self.host,
|
||||
"test",
|
||||
"src/tools/cargo",
|
||||
SourceType::Submodule,
|
||||
&[]);
|
||||
Mode::ToolRustc,
|
||||
self.host,
|
||||
"test",
|
||||
"src/tools/cargo",
|
||||
SourceType::Submodule,
|
||||
&[],
|
||||
);
|
||||
|
||||
if !builder.fail_fast {
|
||||
cargo.arg("--no-fail-fast");
|
||||
|
@ -254,10 +241,7 @@ impl Step for Rls {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Rls {
|
||||
stage: run.builder.top_stage,
|
||||
host: run.target,
|
||||
});
|
||||
run.builder.ensure(Rls { stage: run.builder.top_stage, host: run.target });
|
||||
}
|
||||
|
||||
/// Runs `cargo test` for the rls.
|
||||
|
@ -266,28 +250,26 @@ impl Step for Rls {
|
|||
let host = self.host;
|
||||
let compiler = builder.compiler(stage, host);
|
||||
|
||||
let build_result = builder.ensure(tool::Rls {
|
||||
compiler,
|
||||
target: self.host,
|
||||
extra_features: Vec::new(),
|
||||
});
|
||||
let build_result =
|
||||
builder.ensure(tool::Rls { compiler, target: self.host, extra_features: Vec::new() });
|
||||
if build_result.is_none() {
|
||||
eprintln!("failed to test rls: could not build");
|
||||
return;
|
||||
}
|
||||
|
||||
let mut cargo = tool::prepare_tool_cargo(builder,
|
||||
compiler,
|
||||
Mode::ToolRustc,
|
||||
host,
|
||||
"test",
|
||||
"src/tools/rls",
|
||||
SourceType::Submodule,
|
||||
&[]);
|
||||
let mut cargo = tool::prepare_tool_cargo(
|
||||
builder,
|
||||
compiler,
|
||||
Mode::ToolRustc,
|
||||
host,
|
||||
"test",
|
||||
"src/tools/rls",
|
||||
SourceType::Submodule,
|
||||
&[],
|
||||
);
|
||||
|
||||
builder.add_rustc_lib_path(compiler, &mut cargo);
|
||||
cargo.arg("--")
|
||||
.args(builder.config.cmd.test_args());
|
||||
cargo.arg("--").args(builder.config.cmd.test_args());
|
||||
|
||||
if try_run(builder, &mut cargo.into()) {
|
||||
builder.save_toolstate("rls", ToolState::TestPass);
|
||||
|
@ -310,10 +292,7 @@ impl Step for Rustfmt {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Rustfmt {
|
||||
stage: run.builder.top_stage,
|
||||
host: run.target,
|
||||
});
|
||||
run.builder.ensure(Rustfmt { stage: run.builder.top_stage, host: run.target });
|
||||
}
|
||||
|
||||
/// Runs `cargo test` for rustfmt.
|
||||
|
@ -332,14 +311,16 @@ impl Step for Rustfmt {
|
|||
return;
|
||||
}
|
||||
|
||||
let mut cargo = tool::prepare_tool_cargo(builder,
|
||||
compiler,
|
||||
Mode::ToolRustc,
|
||||
host,
|
||||
"test",
|
||||
"src/tools/rustfmt",
|
||||
SourceType::Submodule,
|
||||
&[]);
|
||||
let mut cargo = tool::prepare_tool_cargo(
|
||||
builder,
|
||||
compiler,
|
||||
Mode::ToolRustc,
|
||||
host,
|
||||
"test",
|
||||
"src/tools/rustfmt",
|
||||
SourceType::Submodule,
|
||||
&[],
|
||||
);
|
||||
|
||||
let dir = testdir(builder, compiler.host);
|
||||
t!(fs::create_dir_all(&dir));
|
||||
|
@ -368,10 +349,7 @@ impl Step for Miri {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Miri {
|
||||
stage: run.builder.top_stage,
|
||||
host: run.target,
|
||||
});
|
||||
run.builder.ensure(Miri { stage: run.builder.top_stage, host: run.target });
|
||||
}
|
||||
|
||||
/// Runs `cargo test` for miri.
|
||||
|
@ -380,11 +358,8 @@ impl Step for Miri {
|
|||
let host = self.host;
|
||||
let compiler = builder.compiler(stage, host);
|
||||
|
||||
let miri = builder.ensure(tool::Miri {
|
||||
compiler,
|
||||
target: self.host,
|
||||
extra_features: Vec::new(),
|
||||
});
|
||||
let miri =
|
||||
builder.ensure(tool::Miri { compiler, target: self.host, extra_features: Vec::new() });
|
||||
if let Some(miri) = miri {
|
||||
let mut cargo = builder.cargo(compiler, Mode::ToolRustc, host, "install");
|
||||
cargo.arg("xargo");
|
||||
|
@ -407,12 +382,7 @@ impl Step for Miri {
|
|||
SourceType::Submodule,
|
||||
&[],
|
||||
);
|
||||
cargo
|
||||
.arg("--bin")
|
||||
.arg("cargo-miri")
|
||||
.arg("--")
|
||||
.arg("miri")
|
||||
.arg("setup");
|
||||
cargo.arg("--bin").arg("cargo-miri").arg("--").arg("miri").arg("setup");
|
||||
|
||||
// Tell `cargo miri` not to worry about the sysroot mismatch (we built with
|
||||
// stage1 but run with stage2).
|
||||
|
@ -441,7 +411,8 @@ impl Step for Miri {
|
|||
String::new()
|
||||
} else {
|
||||
builder.verbose(&format!("running: {:?}", cargo));
|
||||
let out = cargo.output()
|
||||
let out = cargo
|
||||
.output()
|
||||
.expect("We already ran `cargo miri setup` before and that worked");
|
||||
assert!(out.status.success(), "`cargo miri setup` returned with non-0 exit code");
|
||||
// Output is "<sysroot>\n".
|
||||
|
@ -497,9 +468,7 @@ impl Step for CompiletestTest {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(CompiletestTest {
|
||||
host: run.target,
|
||||
});
|
||||
run.builder.ensure(CompiletestTest { host: run.target });
|
||||
}
|
||||
|
||||
/// Runs `cargo test` for compiletest.
|
||||
|
@ -507,14 +476,16 @@ impl Step for CompiletestTest {
|
|||
let host = self.host;
|
||||
let compiler = builder.compiler(0, host);
|
||||
|
||||
let cargo = tool::prepare_tool_cargo(builder,
|
||||
compiler,
|
||||
Mode::ToolBootstrap,
|
||||
host,
|
||||
"test",
|
||||
"src/tools/compiletest",
|
||||
SourceType::InTree,
|
||||
&[]);
|
||||
let cargo = tool::prepare_tool_cargo(
|
||||
builder,
|
||||
compiler,
|
||||
Mode::ToolBootstrap,
|
||||
host,
|
||||
"test",
|
||||
"src/tools/compiletest",
|
||||
SourceType::InTree,
|
||||
&[],
|
||||
);
|
||||
|
||||
try_run(builder, &mut cargo.into());
|
||||
}
|
||||
|
@ -536,10 +507,7 @@ impl Step for Clippy {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Clippy {
|
||||
stage: run.builder.top_stage,
|
||||
host: run.target,
|
||||
});
|
||||
run.builder.ensure(Clippy { stage: run.builder.top_stage, host: run.target });
|
||||
}
|
||||
|
||||
/// Runs `cargo test` for clippy.
|
||||
|
@ -554,22 +522,22 @@ impl Step for Clippy {
|
|||
extra_features: Vec::new(),
|
||||
});
|
||||
if let Some(clippy) = clippy {
|
||||
let mut cargo = tool::prepare_tool_cargo(builder,
|
||||
compiler,
|
||||
Mode::ToolRustc,
|
||||
host,
|
||||
"test",
|
||||
"src/tools/clippy",
|
||||
SourceType::Submodule,
|
||||
&[]);
|
||||
let mut cargo = tool::prepare_tool_cargo(
|
||||
builder,
|
||||
compiler,
|
||||
Mode::ToolRustc,
|
||||
host,
|
||||
"test",
|
||||
"src/tools/clippy",
|
||||
SourceType::Submodule,
|
||||
&[],
|
||||
);
|
||||
|
||||
// clippy tests need to know about the stage sysroot
|
||||
cargo.env("SYSROOT", builder.sysroot(compiler));
|
||||
cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
|
||||
cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
|
||||
let host_libs = builder
|
||||
.stage_out(compiler, Mode::ToolRustc)
|
||||
.join(builder.cargo_dir());
|
||||
let host_libs = builder.stage_out(compiler, Mode::ToolRustc).join(builder.cargo_dir());
|
||||
let target_libs = builder
|
||||
.stage_out(compiler, Mode::ToolRustc)
|
||||
.join(&self.host)
|
||||
|
@ -623,19 +591,10 @@ impl Step for RustdocTheme {
|
|||
let rustdoc = builder.out.join("bootstrap/debug/rustdoc");
|
||||
let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
|
||||
cmd.arg(rustdoc.to_str().unwrap())
|
||||
.arg(
|
||||
builder
|
||||
.src
|
||||
.join("src/librustdoc/html/static/themes")
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
)
|
||||
.arg(builder.src.join("src/librustdoc/html/static/themes").to_str().unwrap())
|
||||
.env("RUSTC_STAGE", self.compiler.stage.to_string())
|
||||
.env("RUSTC_SYSROOT", builder.sysroot(self.compiler))
|
||||
.env(
|
||||
"RUSTDOC_LIBDIR",
|
||||
builder.sysroot_libdir(self.compiler, self.compiler.host),
|
||||
)
|
||||
.env("RUSTDOC_LIBDIR", builder.sysroot_libdir(self.compiler, self.compiler.host))
|
||||
.env("CFG_RELEASE_CHANNEL", &builder.config.channel)
|
||||
.env("RUSTDOC_REAL", builder.rustdoc(self.compiler))
|
||||
.env("RUSTDOC_CRATE_VERSION", builder.rust_version())
|
||||
|
@ -663,25 +622,17 @@ impl Step for RustdocJSStd {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(RustdocJSStd {
|
||||
host: run.host,
|
||||
target: run.target,
|
||||
});
|
||||
run.builder.ensure(RustdocJSStd { host: run.host, target: run.target });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
if let Some(ref nodejs) = builder.config.nodejs {
|
||||
let mut command = Command::new(nodejs);
|
||||
command.args(&["src/tools/rustdoc-js-std/tester.js", &*self.host]);
|
||||
builder.ensure(crate::doc::Std {
|
||||
target: self.target,
|
||||
stage: builder.top_stage,
|
||||
});
|
||||
builder.ensure(crate::doc::Std { target: self.target, stage: builder.top_stage });
|
||||
builder.run(&mut command);
|
||||
} else {
|
||||
builder.info(
|
||||
"No nodejs found, skipping \"src/test/rustdoc-js-std\" tests"
|
||||
);
|
||||
builder.info("No nodejs found, skipping \"src/test/rustdoc-js-std\" tests");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -704,11 +655,7 @@ impl Step for RustdocJSNotStd {
|
|||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
let compiler = run.builder.compiler(run.builder.top_stage, run.host);
|
||||
run.builder.ensure(RustdocJSNotStd {
|
||||
host: run.host,
|
||||
target: run.target,
|
||||
compiler,
|
||||
});
|
||||
run.builder.ensure(RustdocJSNotStd { host: run.host, target: run.target, compiler });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
|
@ -722,9 +669,7 @@ impl Step for RustdocJSNotStd {
|
|||
compare_mode: None,
|
||||
});
|
||||
} else {
|
||||
builder.info(
|
||||
"No nodejs found, skipping \"src/test/rustdoc-js\" tests"
|
||||
);
|
||||
builder.info("No nodejs found, skipping \"src/test/rustdoc-js\" tests");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -747,11 +692,7 @@ impl Step for RustdocUi {
|
|||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
let compiler = run.builder.compiler(run.builder.top_stage, run.host);
|
||||
run.builder.ensure(RustdocUi {
|
||||
host: run.host,
|
||||
target: run.target,
|
||||
compiler,
|
||||
});
|
||||
run.builder.ensure(RustdocUi { host: run.host, target: run.target, compiler });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
|
@ -818,37 +759,55 @@ fn testdir(builder: &Builder<'_>, host: Interned<String>) -> PathBuf {
|
|||
macro_rules! default_test {
|
||||
($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr }) => {
|
||||
test!($name { path: $path, mode: $mode, suite: $suite, default: true, host: false });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! default_test_with_compare_mode {
|
||||
($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr,
|
||||
compare_mode: $compare_mode:expr }) => {
|
||||
test_with_compare_mode!($name { path: $path, mode: $mode, suite: $suite, default: true,
|
||||
host: false, compare_mode: $compare_mode });
|
||||
}
|
||||
test_with_compare_mode!($name {
|
||||
path: $path,
|
||||
mode: $mode,
|
||||
suite: $suite,
|
||||
default: true,
|
||||
host: false,
|
||||
compare_mode: $compare_mode
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! host_test {
|
||||
($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr }) => {
|
||||
test!($name { path: $path, mode: $mode, suite: $suite, default: true, host: true });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! test {
|
||||
($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr, default: $default:expr,
|
||||
host: $host:expr }) => {
|
||||
test_definitions!($name { path: $path, mode: $mode, suite: $suite, default: $default,
|
||||
host: $host, compare_mode: None });
|
||||
}
|
||||
test_definitions!($name {
|
||||
path: $path,
|
||||
mode: $mode,
|
||||
suite: $suite,
|
||||
default: $default,
|
||||
host: $host,
|
||||
compare_mode: None
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! test_with_compare_mode {
|
||||
($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr, default: $default:expr,
|
||||
host: $host:expr, compare_mode: $compare_mode:expr }) => {
|
||||
test_definitions!($name { path: $path, mode: $mode, suite: $suite, default: $default,
|
||||
host: $host, compare_mode: Some($compare_mode) });
|
||||
}
|
||||
test_definitions!($name {
|
||||
path: $path,
|
||||
mode: $mode,
|
||||
suite: $suite,
|
||||
default: $default,
|
||||
host: $host,
|
||||
compare_mode: Some($compare_mode)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! test_definitions {
|
||||
|
@ -878,10 +837,7 @@ macro_rules! test_definitions {
|
|||
fn make_run(run: RunConfig<'_>) {
|
||||
let compiler = run.builder.compiler(run.builder.top_stage, run.host);
|
||||
|
||||
run.builder.ensure($name {
|
||||
compiler,
|
||||
target: run.target,
|
||||
});
|
||||
run.builder.ensure($name { compiler, target: run.target });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
|
@ -895,7 +851,7 @@ macro_rules! test_definitions {
|
|||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
default_test_with_compare_mode!(Ui {
|
||||
|
@ -911,11 +867,7 @@ default_test!(CompileFail {
|
|||
suite: "compile-fail"
|
||||
});
|
||||
|
||||
default_test!(RunFail {
|
||||
path: "src/test/run-fail",
|
||||
mode: "run-fail",
|
||||
suite: "run-fail"
|
||||
});
|
||||
default_test!(RunFail { path: "src/test/run-fail", mode: "run-fail", suite: "run-fail" });
|
||||
|
||||
default_test!(RunPassValgrind {
|
||||
path: "src/test/run-pass-valgrind",
|
||||
|
@ -923,17 +875,9 @@ default_test!(RunPassValgrind {
|
|||
suite: "run-pass-valgrind"
|
||||
});
|
||||
|
||||
default_test!(MirOpt {
|
||||
path: "src/test/mir-opt",
|
||||
mode: "mir-opt",
|
||||
suite: "mir-opt"
|
||||
});
|
||||
default_test!(MirOpt { path: "src/test/mir-opt", mode: "mir-opt", suite: "mir-opt" });
|
||||
|
||||
default_test!(Codegen {
|
||||
path: "src/test/codegen",
|
||||
mode: "codegen",
|
||||
suite: "codegen"
|
||||
});
|
||||
default_test!(Codegen { path: "src/test/codegen", mode: "codegen", suite: "codegen" });
|
||||
|
||||
default_test!(CodegenUnits {
|
||||
path: "src/test/codegen-units",
|
||||
|
@ -947,29 +891,13 @@ default_test!(Incremental {
|
|||
suite: "incremental"
|
||||
});
|
||||
|
||||
default_test!(Debuginfo {
|
||||
path: "src/test/debuginfo",
|
||||
mode: "debuginfo",
|
||||
suite: "debuginfo"
|
||||
});
|
||||
default_test!(Debuginfo { path: "src/test/debuginfo", mode: "debuginfo", suite: "debuginfo" });
|
||||
|
||||
host_test!(UiFullDeps {
|
||||
path: "src/test/ui-fulldeps",
|
||||
mode: "ui",
|
||||
suite: "ui-fulldeps"
|
||||
});
|
||||
host_test!(UiFullDeps { path: "src/test/ui-fulldeps", mode: "ui", suite: "ui-fulldeps" });
|
||||
|
||||
host_test!(Rustdoc {
|
||||
path: "src/test/rustdoc",
|
||||
mode: "rustdoc",
|
||||
suite: "rustdoc"
|
||||
});
|
||||
host_test!(Rustdoc { path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" });
|
||||
|
||||
host_test!(Pretty {
|
||||
path: "src/test/pretty",
|
||||
mode: "pretty",
|
||||
suite: "pretty"
|
||||
});
|
||||
host_test!(Pretty { path: "src/test/pretty", mode: "pretty", suite: "pretty" });
|
||||
test!(RunFailPretty {
|
||||
path: "src/test/run-fail/pretty",
|
||||
mode: "pretty",
|
||||
|
@ -985,11 +913,7 @@ test!(RunPassValgrindPretty {
|
|||
host: true
|
||||
});
|
||||
|
||||
default_test!(RunMake {
|
||||
path: "src/test/run-make",
|
||||
mode: "run-make",
|
||||
suite: "run-make"
|
||||
});
|
||||
default_test!(RunMake { path: "src/test/run-make", mode: "run-make", suite: "run-make" });
|
||||
|
||||
host_test!(RunMakeFullDeps {
|
||||
path: "src/test/run-make-fulldeps",
|
||||
|
@ -997,11 +921,7 @@ host_test!(RunMakeFullDeps {
|
|||
suite: "run-make-fulldeps"
|
||||
});
|
||||
|
||||
default_test!(Assembly {
|
||||
path: "src/test/assembly",
|
||||
mode: "assembly",
|
||||
suite: "assembly"
|
||||
});
|
||||
default_test!(Assembly { path: "src/test/assembly", mode: "assembly", suite: "assembly" });
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
struct Compiletest {
|
||||
|
@ -1048,10 +968,8 @@ impl Step for Compiletest {
|
|||
});
|
||||
}
|
||||
|
||||
builder.ensure(dist::DebuggerScripts {
|
||||
sysroot: builder.sysroot(compiler),
|
||||
host: target,
|
||||
});
|
||||
builder
|
||||
.ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler), host: target });
|
||||
}
|
||||
|
||||
if suite.ends_with("fulldeps") {
|
||||
|
@ -1077,10 +995,8 @@ impl Step for Compiletest {
|
|||
// compiletest currently has... a lot of arguments, so let's just pass all
|
||||
// of them!
|
||||
|
||||
cmd.arg("--compile-lib-path")
|
||||
.arg(builder.rustc_libdir(compiler));
|
||||
cmd.arg("--run-lib-path")
|
||||
.arg(builder.sysroot_libdir(compiler, target));
|
||||
cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(compiler));
|
||||
cmd.arg("--run-lib-path").arg(builder.sysroot_libdir(compiler, target));
|
||||
cmd.arg("--rustc-path").arg(builder.rustc(compiler));
|
||||
|
||||
let is_rustdoc = suite.ends_with("rustdoc-ui") || suite.ends_with("rustdoc-js");
|
||||
|
@ -1091,33 +1007,25 @@ impl Step for Compiletest {
|
|||
|| (mode == "ui" && is_rustdoc)
|
||||
|| mode == "js-doc-test"
|
||||
{
|
||||
cmd.arg("--rustdoc-path")
|
||||
.arg(builder.rustdoc(compiler));
|
||||
cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler));
|
||||
}
|
||||
|
||||
cmd.arg("--src-base")
|
||||
.arg(builder.src.join("src/test").join(suite));
|
||||
cmd.arg("--build-base")
|
||||
.arg(testdir(builder, compiler.host).join(suite));
|
||||
cmd.arg("--stage-id")
|
||||
.arg(format!("stage{}-{}", compiler.stage, target));
|
||||
cmd.arg("--src-base").arg(builder.src.join("src/test").join(suite));
|
||||
cmd.arg("--build-base").arg(testdir(builder, compiler.host).join(suite));
|
||||
cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target));
|
||||
cmd.arg("--mode").arg(mode);
|
||||
cmd.arg("--target").arg(target);
|
||||
cmd.arg("--host").arg(&*compiler.host);
|
||||
cmd.arg("--llvm-filecheck")
|
||||
.arg(builder.llvm_filecheck(builder.config.build));
|
||||
cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.build));
|
||||
|
||||
if builder.config.cmd.bless() {
|
||||
cmd.arg("--bless");
|
||||
}
|
||||
|
||||
let compare_mode = builder.config.cmd.compare_mode().or_else(|| {
|
||||
if builder.config.test_compare_mode {
|
||||
self.compare_mode
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
let compare_mode =
|
||||
builder.config.cmd.compare_mode().or_else(|| {
|
||||
if builder.config.test_compare_mode { self.compare_mode } else { None }
|
||||
});
|
||||
|
||||
if let Some(ref pass) = builder.config.cmd.pass() {
|
||||
cmd.arg("--pass");
|
||||
|
@ -1128,11 +1036,7 @@ impl Step for Compiletest {
|
|||
cmd.arg("--nodejs").arg(nodejs);
|
||||
}
|
||||
|
||||
let mut flags = if is_rustdoc {
|
||||
Vec::new()
|
||||
} else {
|
||||
vec!["-Crpath".to_string()]
|
||||
};
|
||||
let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
|
||||
if !is_rustdoc {
|
||||
if builder.config.rust_optimize_tests {
|
||||
flags.push("-O".to_string());
|
||||
|
@ -1147,17 +1051,11 @@ impl Step for Compiletest {
|
|||
}
|
||||
|
||||
let mut hostflags = flags.clone();
|
||||
hostflags.push(format!(
|
||||
"-Lnative={}",
|
||||
builder.test_helpers_out(compiler.host).display()
|
||||
));
|
||||
hostflags.push(format!("-Lnative={}", builder.test_helpers_out(compiler.host).display()));
|
||||
cmd.arg("--host-rustcflags").arg(hostflags.join(" "));
|
||||
|
||||
let mut targetflags = flags;
|
||||
targetflags.push(format!(
|
||||
"-Lnative={}",
|
||||
builder.test_helpers_out(target).display()
|
||||
));
|
||||
targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
|
||||
cmd.arg("--target-rustcflags").arg(targetflags.join(" "));
|
||||
|
||||
cmd.arg("--docck-python").arg(builder.python());
|
||||
|
@ -1178,9 +1076,10 @@ impl Step for Compiletest {
|
|||
let run = |cmd: &mut Command| {
|
||||
cmd.output().map(|output| {
|
||||
String::from_utf8_lossy(&output.stdout)
|
||||
.lines().next().unwrap_or_else(|| {
|
||||
panic!("{:?} failed {:?}", cmd, output)
|
||||
}).to_string()
|
||||
.lines()
|
||||
.next()
|
||||
.unwrap_or_else(|| panic!("{:?} failed {:?}", cmd, output))
|
||||
.to_string()
|
||||
})
|
||||
};
|
||||
let lldb_exe = if builder.config.lldb_enabled {
|
||||
|
@ -1192,7 +1091,7 @@ impl Step for Compiletest {
|
|||
let lldb_version = Command::new(&lldb_exe)
|
||||
.arg("--version")
|
||||
.output()
|
||||
.map(|output| { String::from_utf8_lossy(&output.stdout).to_string() })
|
||||
.map(|output| String::from_utf8_lossy(&output.stdout).to_string())
|
||||
.ok();
|
||||
if let Some(ref vers) = lldb_version {
|
||||
cmd.arg("--lldb-version").arg(vers);
|
||||
|
@ -1216,11 +1115,9 @@ impl Step for Compiletest {
|
|||
// Get test-args by striping suite path
|
||||
let mut test_args: Vec<&str> = paths
|
||||
.iter()
|
||||
.map(|p| {
|
||||
match p.strip_prefix(".") {
|
||||
Ok(path) => path,
|
||||
Err(_) => p,
|
||||
}
|
||||
.map(|p| match p.strip_prefix(".") {
|
||||
Ok(path) => path,
|
||||
Err(_) => p,
|
||||
})
|
||||
.filter(|p| p.starts_with(suite_path) && (p.is_dir() || p.is_file()))
|
||||
.filter_map(|p| {
|
||||
|
@ -1250,9 +1147,7 @@ impl Step for Compiletest {
|
|||
}
|
||||
|
||||
if builder.config.llvm_enabled() {
|
||||
let llvm_config = builder.ensure(native::Llvm {
|
||||
target: builder.config.build,
|
||||
});
|
||||
let llvm_config = builder.ensure(native::Llvm { target: builder.config.build });
|
||||
if !builder.config.dry_run {
|
||||
let llvm_version = output(Command::new(&llvm_config).arg("--version"));
|
||||
cmd.arg("--llvm-version").arg(llvm_version);
|
||||
|
@ -1282,23 +1177,24 @@ impl Step for Compiletest {
|
|||
|
||||
// The llvm/bin directory contains many useful cross-platform
|
||||
// tools. Pass the path to run-make tests so they can use them.
|
||||
let llvm_bin_path = llvm_config.parent()
|
||||
let llvm_bin_path = llvm_config
|
||||
.parent()
|
||||
.expect("Expected llvm-config to be contained in directory");
|
||||
assert!(llvm_bin_path.is_dir());
|
||||
cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
|
||||
|
||||
// If LLD is available, add it to the PATH
|
||||
if builder.config.lld_enabled {
|
||||
let lld_install_root = builder.ensure(native::Lld {
|
||||
target: builder.config.build,
|
||||
});
|
||||
let lld_install_root =
|
||||
builder.ensure(native::Lld { target: builder.config.build });
|
||||
|
||||
let lld_bin_path = lld_install_root.join("bin");
|
||||
|
||||
let old_path = env::var_os("PATH").unwrap_or_default();
|
||||
let new_path = env::join_paths(std::iter::once(lld_bin_path)
|
||||
.chain(env::split_paths(&old_path)))
|
||||
.expect("Could not add LLD bin path to PATH");
|
||||
let new_path = env::join_paths(
|
||||
std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
|
||||
)
|
||||
.expect("Could not add LLD bin path to PATH");
|
||||
cmd.env("PATH", new_path);
|
||||
}
|
||||
}
|
||||
|
@ -1318,8 +1214,7 @@ impl Step for Compiletest {
|
|||
}
|
||||
|
||||
if builder.remote_tested(target) {
|
||||
cmd.arg("--remote-test-client")
|
||||
.arg(builder.tool_exe(Tool::RemoteTestClient));
|
||||
cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
|
||||
}
|
||||
|
||||
// Running a C compiler on MSVC requires a few env vars to be set, to be
|
||||
|
@ -1349,7 +1244,6 @@ impl Step for Compiletest {
|
|||
std::fs::create_dir_all(&tmp).unwrap();
|
||||
cmd.env("RUST_TEST_TMPDIR", tmp);
|
||||
|
||||
|
||||
cmd.arg("--adb-path").arg("adb");
|
||||
cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
|
||||
if target.contains("android") {
|
||||
|
@ -1409,10 +1303,7 @@ impl Step for DocTest {
|
|||
fn run(self, builder: &Builder<'_>) {
|
||||
let compiler = self.compiler;
|
||||
|
||||
builder.ensure(compile::Std {
|
||||
compiler,
|
||||
target: compiler.host,
|
||||
});
|
||||
builder.ensure(compile::Std { compiler, target: compiler.host });
|
||||
|
||||
// Do a breadth-first traversal of the `src/doc` directory and just run
|
||||
// tests for all files that end in `*.md`
|
||||
|
@ -1516,9 +1407,8 @@ impl Step for ErrorIndex {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(ErrorIndex {
|
||||
compiler: run.builder.compiler(run.builder.top_stage, run.host),
|
||||
});
|
||||
run.builder
|
||||
.ensure(ErrorIndex { compiler: run.builder.compiler(run.builder.top_stage, run.host) });
|
||||
}
|
||||
|
||||
/// Runs the error index generator tool to execute the tests located in the error
|
||||
|
@ -1530,10 +1420,7 @@ impl Step for ErrorIndex {
|
|||
fn run(self, builder: &Builder<'_>) {
|
||||
let compiler = self.compiler;
|
||||
|
||||
builder.ensure(compile::Std {
|
||||
compiler,
|
||||
target: compiler.host,
|
||||
});
|
||||
builder.ensure(compile::Std { compiler, target: compiler.host });
|
||||
|
||||
let dir = testdir(builder, compiler.host);
|
||||
t!(fs::create_dir_all(&dir));
|
||||
|
@ -1543,9 +1430,7 @@ impl Step for ErrorIndex {
|
|||
builder,
|
||||
builder.compiler(compiler.stage, builder.config.build),
|
||||
);
|
||||
tool.arg("markdown")
|
||||
.arg(&output)
|
||||
.env("CFG_BUILD", &builder.config.build);
|
||||
tool.arg("markdown").arg(&output).env("CFG_BUILD", &builder.config.build);
|
||||
|
||||
builder.info(&format!("Testing error-index stage{}", compiler.stage));
|
||||
let _time = util::timeit(&builder);
|
||||
|
@ -1825,23 +1710,12 @@ impl Step for Crate {
|
|||
if target.contains("emscripten") {
|
||||
cargo.env(
|
||||
format!("CARGO_TARGET_{}_RUNNER", envify(&target)),
|
||||
builder
|
||||
.config
|
||||
.nodejs
|
||||
.as_ref()
|
||||
.expect("nodejs not configured"),
|
||||
builder.config.nodejs.as_ref().expect("nodejs not configured"),
|
||||
);
|
||||
} else if target.starts_with("wasm32") {
|
||||
let node = builder
|
||||
.config
|
||||
.nodejs
|
||||
.as_ref()
|
||||
.expect("nodejs not configured");
|
||||
let runner = format!(
|
||||
"{} {}/src/etc/wasm32-shim.js",
|
||||
node.display(),
|
||||
builder.src.display()
|
||||
);
|
||||
let node = builder.config.nodejs.as_ref().expect("nodejs not configured");
|
||||
let runner =
|
||||
format!("{} {}/src/etc/wasm32-shim.js", node.display(), builder.src.display());
|
||||
cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)), &runner);
|
||||
} else if builder.remote_tested(target) {
|
||||
cargo.env(
|
||||
|
@ -1879,10 +1753,7 @@ impl Step for CrateRustdoc {
|
|||
|
||||
let test_kind = builder.kind.into();
|
||||
|
||||
builder.ensure(CrateRustdoc {
|
||||
host: run.host,
|
||||
test_kind,
|
||||
});
|
||||
builder.ensure(CrateRustdoc { host: run.host, test_kind });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
|
@ -1892,14 +1763,16 @@ impl Step for CrateRustdoc {
|
|||
let target = compiler.host;
|
||||
builder.ensure(compile::Rustc { compiler, target });
|
||||
|
||||
let mut cargo = tool::prepare_tool_cargo(builder,
|
||||
compiler,
|
||||
Mode::ToolRustc,
|
||||
target,
|
||||
test_kind.subcommand(),
|
||||
"src/tools/rustdoc",
|
||||
SourceType::InTree,
|
||||
&[]);
|
||||
let mut cargo = tool::prepare_tool_cargo(
|
||||
builder,
|
||||
compiler,
|
||||
Mode::ToolRustc,
|
||||
target,
|
||||
test_kind.subcommand(),
|
||||
"src/tools/rustdoc",
|
||||
SourceType::InTree,
|
||||
&[],
|
||||
);
|
||||
if test_kind.subcommand() == "test" && !builder.fail_fast {
|
||||
cargo.arg("--no-fail-fast");
|
||||
}
|
||||
|
@ -1961,18 +1834,13 @@ impl Step for RemoteCopyLibs {
|
|||
builder.info(&format!("REMOTE copy libs to emulator ({})", target));
|
||||
t!(fs::create_dir_all(builder.out.join("tmp")));
|
||||
|
||||
let server = builder.ensure(tool::RemoteTestServer {
|
||||
compiler: compiler.with_stage(0),
|
||||
target,
|
||||
});
|
||||
let server =
|
||||
builder.ensure(tool::RemoteTestServer { compiler: compiler.with_stage(0), target });
|
||||
|
||||
// Spawn the emulator and wait for it to come online
|
||||
let tool = builder.tool_exe(Tool::RemoteTestClient);
|
||||
let mut cmd = Command::new(&tool);
|
||||
cmd.arg("spawn-emulator")
|
||||
.arg(target)
|
||||
.arg(&server)
|
||||
.arg(builder.out.join("tmp"));
|
||||
cmd.arg("spawn-emulator").arg(target).arg(&server).arg(builder.out.join("tmp"));
|
||||
if let Some(rootfs) = builder.qemu_rootfs(target) {
|
||||
cmd.arg(rootfs);
|
||||
}
|
||||
|
@ -2027,9 +1895,7 @@ impl Step for Distcheck {
|
|||
.current_dir(&dir),
|
||||
);
|
||||
builder.run(
|
||||
Command::new(build_helper::make(&builder.config.build))
|
||||
.arg("check")
|
||||
.current_dir(&dir),
|
||||
Command::new(build_helper::make(&builder.config.build)).arg("check").current_dir(&dir),
|
||||
);
|
||||
|
||||
// Now make sure that rust-src has all of libstd's dependencies
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
use std::fs;
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Command, exit};
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{exit, Command};
|
||||
|
||||
use build_helper::t;
|
||||
|
||||
use crate::Mode;
|
||||
use crate::Compiler;
|
||||
use crate::builder::{Step, RunConfig, ShouldRun, Builder, Cargo as CargoCommand};
|
||||
use crate::util::{exe, add_lib_path, CiEnv};
|
||||
use crate::compile;
|
||||
use crate::channel::GitInfo;
|
||||
use crate::channel;
|
||||
use crate::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step};
|
||||
use crate::cache::Interned;
|
||||
use crate::channel;
|
||||
use crate::channel::GitInfo;
|
||||
use crate::compile;
|
||||
use crate::toolstate::ToolState;
|
||||
use crate::util::{add_lib_path, exe, CiEnv};
|
||||
use crate::Compiler;
|
||||
use crate::Mode;
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum SourceType {
|
||||
|
@ -53,14 +53,10 @@ impl Step for ToolBuild {
|
|||
let is_optional_tool = self.is_optional_tool;
|
||||
|
||||
match self.mode {
|
||||
Mode::ToolRustc => {
|
||||
builder.ensure(compile::Rustc { compiler, target })
|
||||
}
|
||||
Mode::ToolStd => {
|
||||
builder.ensure(compile::Std { compiler, target })
|
||||
}
|
||||
Mode::ToolRustc => builder.ensure(compile::Rustc { compiler, target }),
|
||||
Mode::ToolStd => builder.ensure(compile::Std { compiler, target }),
|
||||
Mode::ToolBootstrap => {} // uses downloaded stage0 compiler libs
|
||||
_ => panic!("unexpected Mode for tool build")
|
||||
_ => panic!("unexpected Mode for tool build"),
|
||||
}
|
||||
|
||||
let cargo = prepare_tool_cargo(
|
||||
|
@ -79,12 +75,7 @@ impl Step for ToolBuild {
|
|||
let is_expected = compile::stream_cargo(builder, cargo, vec![], &mut |msg| {
|
||||
// Only care about big things like the RLS/Cargo for now
|
||||
match tool {
|
||||
| "rls"
|
||||
| "cargo"
|
||||
| "clippy-driver"
|
||||
| "miri"
|
||||
| "rustfmt"
|
||||
=> {}
|
||||
"rls" | "cargo" | "clippy-driver" | "miri" | "rustfmt" => {}
|
||||
|
||||
_ => return,
|
||||
}
|
||||
|
@ -94,9 +85,7 @@ impl Step for ToolBuild {
|
|||
features,
|
||||
filenames,
|
||||
target: _,
|
||||
} => {
|
||||
(package_id, features, filenames)
|
||||
}
|
||||
} => (package_id, features, filenames),
|
||||
_ => return,
|
||||
};
|
||||
let features = features.iter().map(|s| s.to_string()).collect::<Vec<_>>();
|
||||
|
@ -105,7 +94,7 @@ impl Step for ToolBuild {
|
|||
let val = (tool, PathBuf::from(&*path), features.clone());
|
||||
// we're only interested in deduplicating rlibs for now
|
||||
if val.1.extension().and_then(|s| s.to_str()) != Some("rlib") {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't worry about compiles that turn out to be host
|
||||
|
@ -132,9 +121,7 @@ impl Step for ToolBuild {
|
|||
// already listed then we need to see if we reused the same
|
||||
// artifact or produced a duplicate.
|
||||
let mut artifacts = builder.tool_artifacts.borrow_mut();
|
||||
let prev_artifacts = artifacts
|
||||
.entry(target)
|
||||
.or_default();
|
||||
let prev_artifacts = artifacts.entry(target).or_default();
|
||||
let prev = match prev_artifacts.get(&*id) {
|
||||
Some(prev) => prev,
|
||||
None => {
|
||||
|
@ -160,21 +147,21 @@ impl Step for ToolBuild {
|
|||
|
||||
// ... and otherwise this looks like we duplicated some sort of
|
||||
// compilation, so record it to generate an error later.
|
||||
duplicates.push((
|
||||
id.to_string(),
|
||||
val,
|
||||
prev.clone(),
|
||||
));
|
||||
duplicates.push((id.to_string(), val, prev.clone()));
|
||||
}
|
||||
});
|
||||
|
||||
if is_expected && !duplicates.is_empty() {
|
||||
println!("duplicate artifacts found when compiling a tool, this \
|
||||
println!(
|
||||
"duplicate artifacts found when compiling a tool, this \
|
||||
typically means that something was recompiled because \
|
||||
a transitive dependency has different features activated \
|
||||
than in a previous build:\n");
|
||||
println!("the following dependencies are duplicated although they \
|
||||
have the same features enabled:");
|
||||
than in a previous build:\n"
|
||||
);
|
||||
println!(
|
||||
"the following dependencies are duplicated although they \
|
||||
have the same features enabled:"
|
||||
);
|
||||
for (id, cur, prev) in duplicates.drain_filter(|(_, cur, prev)| cur.2 == prev.2) {
|
||||
println!(" {}", id);
|
||||
// same features
|
||||
|
@ -185,24 +172,33 @@ impl Step for ToolBuild {
|
|||
println!(" {}", id);
|
||||
let cur_features: HashSet<_> = cur.2.into_iter().collect();
|
||||
let prev_features: HashSet<_> = prev.2.into_iter().collect();
|
||||
println!(" `{}` additionally enabled features {:?} at {:?}",
|
||||
cur.0, &cur_features - &prev_features, cur.1);
|
||||
println!(" `{}` additionally enabled features {:?} at {:?}",
|
||||
prev.0, &prev_features - &cur_features, prev.1);
|
||||
println!(
|
||||
" `{}` additionally enabled features {:?} at {:?}",
|
||||
cur.0,
|
||||
&cur_features - &prev_features,
|
||||
cur.1
|
||||
);
|
||||
println!(
|
||||
" `{}` additionally enabled features {:?} at {:?}",
|
||||
prev.0,
|
||||
&prev_features - &cur_features,
|
||||
prev.1
|
||||
);
|
||||
}
|
||||
println!();
|
||||
println!("to fix this you will probably want to edit the local \
|
||||
println!(
|
||||
"to fix this you will probably want to edit the local \
|
||||
src/tools/rustc-workspace-hack/Cargo.toml crate, as \
|
||||
that will update the dependency graph to ensure that \
|
||||
these crates all share the same feature set");
|
||||
these crates all share the same feature set"
|
||||
);
|
||||
panic!("tools should not compile multiple copies of the same crate");
|
||||
}
|
||||
|
||||
builder.save_toolstate(tool, if is_expected {
|
||||
ToolState::TestFail
|
||||
} else {
|
||||
ToolState::BuildFail
|
||||
});
|
||||
builder.save_toolstate(
|
||||
tool,
|
||||
if is_expected { ToolState::TestFail } else { ToolState::BuildFail },
|
||||
);
|
||||
|
||||
if !is_expected {
|
||||
if !is_optional_tool {
|
||||
|
@ -211,8 +207,8 @@ impl Step for ToolBuild {
|
|||
None
|
||||
}
|
||||
} else {
|
||||
let cargo_out = builder.cargo_out(compiler, self.mode, target)
|
||||
.join(exe(tool, &compiler.host));
|
||||
let cargo_out =
|
||||
builder.cargo_out(compiler, self.mode, target).join(exe(tool, &compiler.host));
|
||||
let bin = builder.tools_dir(compiler).join(exe(tool, &compiler.host));
|
||||
builder.copy(&cargo_out, &bin);
|
||||
Some(bin)
|
||||
|
@ -240,12 +236,12 @@ pub fn prepare_tool_cargo(
|
|||
|
||||
let mut features = extra_features.iter().cloned().collect::<Vec<_>>();
|
||||
if builder.build.config.cargo_native_static {
|
||||
if path.ends_with("cargo") ||
|
||||
path.ends_with("rls") ||
|
||||
path.ends_with("clippy") ||
|
||||
path.ends_with("miri") ||
|
||||
path.ends_with("rustbook") ||
|
||||
path.ends_with("rustfmt")
|
||||
if path.ends_with("cargo")
|
||||
|| path.ends_with("rls")
|
||||
|| path.ends_with("clippy")
|
||||
|| path.ends_with("miri")
|
||||
|| path.ends_with("rustbook")
|
||||
|| path.ends_with("rustfmt")
|
||||
{
|
||||
cargo.env("LIBZ_SYS_STATIC", "1");
|
||||
features.push("rustc-workspace-hack/all-static".to_string());
|
||||
|
@ -395,9 +391,7 @@ pub struct ErrorIndex {
|
|||
|
||||
impl ErrorIndex {
|
||||
pub fn command(builder: &Builder<'_>, compiler: Compiler) -> Command {
|
||||
let mut cmd = Command::new(builder.ensure(ErrorIndex {
|
||||
compiler
|
||||
}));
|
||||
let mut cmd = Command::new(builder.ensure(ErrorIndex { compiler }));
|
||||
add_lib_path(
|
||||
vec![PathBuf::from(&builder.sysroot_libdir(compiler, compiler.host))],
|
||||
&mut cmd,
|
||||
|
@ -417,22 +411,23 @@ impl Step for ErrorIndex {
|
|||
// Compile the error-index in the same stage as rustdoc to avoid
|
||||
// recompiling rustdoc twice if we can.
|
||||
let stage = if run.builder.top_stage >= 2 { run.builder.top_stage } else { 0 };
|
||||
run.builder.ensure(ErrorIndex {
|
||||
compiler: run.builder.compiler(stage, run.builder.config.build),
|
||||
});
|
||||
run.builder
|
||||
.ensure(ErrorIndex { compiler: run.builder.compiler(stage, run.builder.config.build) });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) -> PathBuf {
|
||||
builder.ensure(ToolBuild {
|
||||
compiler: self.compiler,
|
||||
target: self.compiler.host,
|
||||
tool: "error_index_generator",
|
||||
mode: Mode::ToolRustc,
|
||||
path: "src/tools/error_index_generator",
|
||||
is_optional_tool: false,
|
||||
source_type: SourceType::InTree,
|
||||
extra_features: Vec::new(),
|
||||
}).expect("expected to build -- essential tool")
|
||||
builder
|
||||
.ensure(ToolBuild {
|
||||
compiler: self.compiler,
|
||||
target: self.compiler.host,
|
||||
tool: "error_index_generator",
|
||||
mode: Mode::ToolRustc,
|
||||
path: "src/tools/error_index_generator",
|
||||
is_optional_tool: false,
|
||||
source_type: SourceType::InTree,
|
||||
extra_features: Vec::new(),
|
||||
})
|
||||
.expect("expected to build -- essential tool")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -457,16 +452,18 @@ impl Step for RemoteTestServer {
|
|||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) -> PathBuf {
|
||||
builder.ensure(ToolBuild {
|
||||
compiler: self.compiler,
|
||||
target: self.target,
|
||||
tool: "remote-test-server",
|
||||
mode: Mode::ToolStd,
|
||||
path: "src/tools/remote-test-server",
|
||||
is_optional_tool: false,
|
||||
source_type: SourceType::InTree,
|
||||
extra_features: Vec::new(),
|
||||
}).expect("expected to build -- essential tool")
|
||||
builder
|
||||
.ensure(ToolBuild {
|
||||
compiler: self.compiler,
|
||||
target: self.target,
|
||||
tool: "remote-test-server",
|
||||
mode: Mode::ToolStd,
|
||||
path: "src/tools/remote-test-server",
|
||||
is_optional_tool: false,
|
||||
source_type: SourceType::InTree,
|
||||
extra_features: Vec::new(),
|
||||
})
|
||||
.expect("expected to build -- essential tool")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -487,9 +484,8 @@ impl Step for Rustdoc {
|
|||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Rustdoc {
|
||||
compiler: run.builder.compiler(run.builder.top_stage, run.host),
|
||||
});
|
||||
run.builder
|
||||
.ensure(Rustdoc { compiler: run.builder.compiler(run.builder.top_stage, run.host) });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) -> PathBuf {
|
||||
|
@ -525,14 +521,17 @@ impl Step for Rustdoc {
|
|||
&[],
|
||||
);
|
||||
|
||||
builder.info(&format!("Building rustdoc for stage{} ({})",
|
||||
target_compiler.stage, target_compiler.host));
|
||||
builder.info(&format!(
|
||||
"Building rustdoc for stage{} ({})",
|
||||
target_compiler.stage, target_compiler.host
|
||||
));
|
||||
builder.run(&mut cargo.into());
|
||||
|
||||
// Cargo adds a number of paths to the dylib search path on windows, which results in
|
||||
// the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
|
||||
// rustdoc a different name.
|
||||
let tool_rustdoc = builder.cargo_out(build_compiler, Mode::ToolRustc, target)
|
||||
let tool_rustdoc = builder
|
||||
.cargo_out(build_compiler, Mode::ToolRustc, target)
|
||||
.join(exe("rustdoc_tool_binary", &target_compiler.host));
|
||||
|
||||
// don't create a stage0-sysroot/bin directory.
|
||||
|
@ -574,16 +573,18 @@ impl Step for Cargo {
|
|||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) -> PathBuf {
|
||||
builder.ensure(ToolBuild {
|
||||
compiler: self.compiler,
|
||||
target: self.target,
|
||||
tool: "cargo",
|
||||
mode: Mode::ToolRustc,
|
||||
path: "src/tools/cargo",
|
||||
is_optional_tool: false,
|
||||
source_type: SourceType::Submodule,
|
||||
extra_features: Vec::new(),
|
||||
}).expect("expected to build -- essential tool")
|
||||
builder
|
||||
.ensure(ToolBuild {
|
||||
compiler: self.compiler,
|
||||
target: self.target,
|
||||
tool: "cargo",
|
||||
mode: Mode::ToolRustc,
|
||||
path: "src/tools/cargo",
|
||||
is_optional_tool: false,
|
||||
source_type: SourceType::Submodule,
|
||||
extra_features: Vec::new(),
|
||||
})
|
||||
.expect("expected to build -- essential tool")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -682,7 +683,7 @@ impl<'a> Builder<'a> {
|
|||
let curpaths = env::split_paths(&curpaths).collect::<Vec<_>>();
|
||||
for &(ref k, ref v) in self.cc[&compiler.host].env() {
|
||||
if k != "PATH" {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
for path in env::split_paths(v) {
|
||||
if !curpaths.contains(&path) {
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
|
||||
use build_helper::t;
|
||||
use std::time;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::fmt;
|
||||
use std::fs;
|
||||
use std::io::{Seek, SeekFrom};
|
||||
use std::collections::HashMap;
|
||||
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
|
||||
use std::fmt;
|
||||
use std::process::Command;
|
||||
use std::path::PathBuf;
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
use std::time;
|
||||
|
||||
// Each cycle is 42 days long (6 weeks); the last week is 35..=42 then.
|
||||
const BETA_WEEK_START: u64 = 35;
|
||||
|
@ -38,11 +38,15 @@ pub enum ToolState {
|
|||
|
||||
impl fmt::Display for ToolState {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", match self {
|
||||
ToolState::TestFail => "test-fail",
|
||||
ToolState::TestPass => "test-pass",
|
||||
ToolState::BuildFail => "build-fail",
|
||||
})
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
ToolState::TestFail => "test-fail",
|
||||
ToolState::TestPass => "test-pass",
|
||||
ToolState::BuildFail => "build-fail",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,9 +124,7 @@ fn check_changed_files(toolstates: &HashMap<Box<str>, ToolState>) {
|
|||
let output = t!(String::from_utf8(output.stdout));
|
||||
|
||||
for (tool, submodule) in STABLE_TOOLS.iter().chain(NIGHTLY_TOOLS.iter()) {
|
||||
let changed = output.lines().any(|l| {
|
||||
l.starts_with("M") && l.ends_with(submodule)
|
||||
});
|
||||
let changed = output.lines().any(|l| l.starts_with("M") && l.ends_with(submodule));
|
||||
eprintln!("Verifying status of {}...", tool);
|
||||
if !changed {
|
||||
continue;
|
||||
|
@ -179,8 +181,10 @@ impl Step for ToolStateCheck {
|
|||
eprintln!("error: Tool `{}` should be test-pass but is {}", tool, state);
|
||||
} else if in_beta_week {
|
||||
did_error = true;
|
||||
eprintln!("error: Tool `{}` should be test-pass but is {} during beta week.",
|
||||
tool, state);
|
||||
eprintln!(
|
||||
"error: Tool `{}` should be test-pass but is {} during beta week.",
|
||||
tool, state
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -210,11 +214,8 @@ impl Builder<'_> {
|
|||
// Ensure the parent directory always exists
|
||||
t!(std::fs::create_dir_all(parent));
|
||||
}
|
||||
let mut file = t!(fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.read(true)
|
||||
.open(path));
|
||||
let mut file =
|
||||
t!(fs::OpenOptions::new().create(true).write(true).read(true).open(path));
|
||||
|
||||
serde_json::from_reader(&mut file).unwrap_or_default()
|
||||
} else {
|
||||
|
@ -233,11 +234,8 @@ impl Builder<'_> {
|
|||
// Ensure the parent directory always exists
|
||||
t!(std::fs::create_dir_all(parent));
|
||||
}
|
||||
let mut file = t!(fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open(path));
|
||||
let mut file =
|
||||
t!(fs::OpenOptions::new().create(true).read(true).write(true).open(path));
|
||||
|
||||
let mut current_toolstates: HashMap<Box<str>, ToolState> =
|
||||
serde_json::from_reader(&mut file).unwrap_or_default();
|
||||
|
@ -275,10 +273,7 @@ impl Builder<'_> {
|
|||
///
|
||||
/// * See <https://help.github.com/articles/about-commit-email-addresses/>
|
||||
/// if a private email by GitHub is wanted.
|
||||
fn commit_toolstate_change(
|
||||
current_toolstate: &ToolstateData,
|
||||
in_beta_week: bool,
|
||||
) {
|
||||
fn commit_toolstate_change(current_toolstate: &ToolstateData, in_beta_week: bool) {
|
||||
fn git_config(key: &str, value: &str) {
|
||||
let status = Command::new("git").arg("config").arg("--global").arg(key).arg(value).status();
|
||||
let success = match status {
|
||||
|
@ -303,7 +298,8 @@ fn commit_toolstate_change(
|
|||
let git_credential_path = PathBuf::from(t!(env::var("HOME"))).join(".git-credentials");
|
||||
t!(fs::write(&git_credential_path, credential));
|
||||
|
||||
let status = Command::new("git").arg("clone")
|
||||
let status = Command::new("git")
|
||||
.arg("clone")
|
||||
.arg("--depth=1")
|
||||
.arg(t!(env::var("TOOLSTATE_REPO")))
|
||||
.status();
|
||||
|
@ -402,10 +398,7 @@ fn change_toolstate(
|
|||
std::process::exit(1);
|
||||
}
|
||||
|
||||
let commit = t!(std::process::Command::new("git")
|
||||
.arg("rev-parse")
|
||||
.arg("HEAD")
|
||||
.output());
|
||||
let commit = t!(std::process::Command::new("git").arg("rev-parse").arg("HEAD").output());
|
||||
let commit = t!(String::from_utf8(commit.stdout));
|
||||
|
||||
let toolstate_serialized = t!(serde_json::to_string(¤t_toolstate));
|
||||
|
|
|
@ -4,36 +4,28 @@
|
|||
//! not a lot of interesting happenings here unfortunately.
|
||||
|
||||
use std::env;
|
||||
use std::str;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::str;
|
||||
use std::time::Instant;
|
||||
|
||||
use build_helper::t;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::builder::Builder;
|
||||
use crate::cache::Interned;
|
||||
use crate::config::Config;
|
||||
|
||||
/// Returns the `name` as the filename of a static library for `target`.
|
||||
pub fn staticlib(name: &str, target: &str) -> String {
|
||||
if target.contains("windows") {
|
||||
format!("{}.lib", name)
|
||||
} else {
|
||||
format!("lib{}.a", name)
|
||||
}
|
||||
if target.contains("windows") { format!("{}.lib", name) } else { format!("lib{}.a", name) }
|
||||
}
|
||||
|
||||
/// Given an executable called `name`, return the filename for the
|
||||
/// executable for a particular target.
|
||||
pub fn exe(name: &str, target: &str) -> String {
|
||||
if target.contains("windows") {
|
||||
format!("{}.exe", name)
|
||||
} else {
|
||||
name.to_string()
|
||||
}
|
||||
if target.contains("windows") { format!("{}.exe", name) } else { name.to_string() }
|
||||
}
|
||||
|
||||
/// Returns `true` if the file name given looks like a dynamic library.
|
||||
|
@ -44,7 +36,7 @@ pub fn is_dylib(name: &str) -> bool {
|
|||
/// Returns the corresponding relative library directory that the compiler's
|
||||
/// dylibs will be found in.
|
||||
pub fn libdir(target: &str) -> &'static str {
|
||||
if target.contains("windows") {"bin"} else {"lib"}
|
||||
if target.contains("windows") { "bin" } else { "lib" }
|
||||
}
|
||||
|
||||
/// Adds a list of lookup paths to `cmd`'s dynamic library lookup path.
|
||||
|
@ -106,9 +98,7 @@ impl Drop for TimeIt {
|
|||
fn drop(&mut self) {
|
||||
let time = self.1.elapsed();
|
||||
if !self.0 {
|
||||
println!("\tfinished in {}.{:03}",
|
||||
time.as_secs(),
|
||||
time.subsec_nanos() / 1_000_000);
|
||||
println!("\tfinished in {}.{:03}", time.as_secs(), time.subsec_nanos() / 1_000_000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +106,9 @@ impl Drop for TimeIt {
|
|||
/// Symlinks two directories, using junctions on Windows and normal symlinks on
|
||||
/// Unix.
|
||||
pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
|
||||
if config.dry_run { return Ok(()); }
|
||||
if config.dry_run {
|
||||
return Ok(());
|
||||
}
|
||||
let _ = fs::remove_dir(dest);
|
||||
return symlink_dir_inner(src, dest);
|
||||
|
||||
|
@ -136,9 +128,9 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
|
|||
#[cfg(windows)]
|
||||
#[allow(nonstandard_style)]
|
||||
fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> {
|
||||
use std::ptr;
|
||||
use std::ffi::OsStr;
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
use std::ptr;
|
||||
|
||||
const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024;
|
||||
const GENERIC_WRITE: DWORD = 0x40000000;
|
||||
|
@ -174,22 +166,25 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
|
|||
}
|
||||
|
||||
extern "system" {
|
||||
fn CreateFileW(lpFileName: LPCWSTR,
|
||||
dwDesiredAccess: DWORD,
|
||||
dwShareMode: DWORD,
|
||||
lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
|
||||
dwCreationDisposition: DWORD,
|
||||
dwFlagsAndAttributes: DWORD,
|
||||
hTemplateFile: HANDLE)
|
||||
-> HANDLE;
|
||||
fn DeviceIoControl(hDevice: HANDLE,
|
||||
dwIoControlCode: DWORD,
|
||||
lpInBuffer: LPVOID,
|
||||
nInBufferSize: DWORD,
|
||||
lpOutBuffer: LPVOID,
|
||||
nOutBufferSize: DWORD,
|
||||
lpBytesReturned: LPDWORD,
|
||||
lpOverlapped: LPOVERLAPPED) -> BOOL;
|
||||
fn CreateFileW(
|
||||
lpFileName: LPCWSTR,
|
||||
dwDesiredAccess: DWORD,
|
||||
dwShareMode: DWORD,
|
||||
lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
|
||||
dwCreationDisposition: DWORD,
|
||||
dwFlagsAndAttributes: DWORD,
|
||||
hTemplateFile: HANDLE,
|
||||
) -> HANDLE;
|
||||
fn DeviceIoControl(
|
||||
hDevice: HANDLE,
|
||||
dwIoControlCode: DWORD,
|
||||
lpInBuffer: LPVOID,
|
||||
nInBufferSize: DWORD,
|
||||
lpOutBuffer: LPVOID,
|
||||
nOutBufferSize: DWORD,
|
||||
lpBytesReturned: LPDWORD,
|
||||
lpOverlapped: LPOVERLAPPED,
|
||||
) -> BOOL;
|
||||
fn CloseHandle(hObject: HANDLE) -> BOOL;
|
||||
}
|
||||
|
||||
|
@ -207,17 +202,18 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
|
|||
let path = to_u16s(junction)?;
|
||||
|
||||
unsafe {
|
||||
let h = CreateFileW(path.as_ptr(),
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
ptr::null_mut(),
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
|
||||
ptr::null_mut());
|
||||
let h = CreateFileW(
|
||||
path.as_ptr(),
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
ptr::null_mut(),
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
|
||||
ptr::null_mut(),
|
||||
);
|
||||
|
||||
let mut data = [0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
|
||||
let db = data.as_mut_ptr()
|
||||
as *mut REPARSE_MOUNTPOINT_DATA_BUFFER;
|
||||
let db = data.as_mut_ptr() as *mut REPARSE_MOUNTPOINT_DATA_BUFFER;
|
||||
let buf = &mut (*db).ReparseTarget as *mut u16;
|
||||
let mut i = 0;
|
||||
// FIXME: this conversion is very hacky
|
||||
|
@ -232,23 +228,21 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
|
|||
(*db).ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
||||
(*db).ReparseTargetMaximumLength = (i * 2) as WORD;
|
||||
(*db).ReparseTargetLength = ((i - 1) * 2) as WORD;
|
||||
(*db).ReparseDataLength =
|
||||
(*db).ReparseTargetLength as DWORD + 12;
|
||||
(*db).ReparseDataLength = (*db).ReparseTargetLength as DWORD + 12;
|
||||
|
||||
let mut ret = 0;
|
||||
let res = DeviceIoControl(h as *mut _,
|
||||
FSCTL_SET_REPARSE_POINT,
|
||||
data.as_ptr() as *mut _,
|
||||
(*db).ReparseDataLength + 8,
|
||||
ptr::null_mut(), 0,
|
||||
&mut ret,
|
||||
ptr::null_mut());
|
||||
let res = DeviceIoControl(
|
||||
h as *mut _,
|
||||
FSCTL_SET_REPARSE_POINT,
|
||||
data.as_ptr() as *mut _,
|
||||
(*db).ReparseDataLength + 8,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
&mut ret,
|
||||
ptr::null_mut(),
|
||||
);
|
||||
|
||||
let out = if res == 0 {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(())
|
||||
};
|
||||
let out = if res == 0 { Err(io::Error::last_os_error()) } else { Ok(()) };
|
||||
CloseHandle(h);
|
||||
out
|
||||
}
|
||||
|
@ -299,8 +293,11 @@ pub fn forcing_clang_based_tests() -> bool {
|
|||
"0" | "no" | "off" => false,
|
||||
other => {
|
||||
// Let's make sure typos don't go unnoticed
|
||||
panic!("Unrecognized option '{}' set in \
|
||||
RUSTBUILD_FORCE_CLANG_BASED_TESTS", other)
|
||||
panic!(
|
||||
"Unrecognized option '{}' set in \
|
||||
RUSTBUILD_FORCE_CLANG_BASED_TESTS",
|
||||
other
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -311,11 +308,9 @@ pub fn forcing_clang_based_tests() -> bool {
|
|||
pub fn use_host_linker(target: &Interned<String>) -> bool {
|
||||
// FIXME: this information should be gotten by checking the linker flavor
|
||||
// of the rustc target
|
||||
!(
|
||||
target.contains("emscripten") ||
|
||||
target.contains("wasm32") ||
|
||||
target.contains("nvptx") ||
|
||||
target.contains("fortanix") ||
|
||||
target.contains("fuchsia")
|
||||
)
|
||||
!(target.contains("emscripten")
|
||||
|| target.contains("wasm32")
|
||||
|| target.contains("nvptx")
|
||||
|| target.contains("fortanix")
|
||||
|| target.contains("fuchsia"))
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use std::fs::File;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, Stdio};
|
||||
use std::thread;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use std::{env, fs};
|
||||
use std::thread;
|
||||
|
||||
/// A helper macro to `unwrap` a result except also print out details like:
|
||||
///
|
||||
|
@ -64,10 +64,7 @@ pub fn run(cmd: &mut Command) {
|
|||
pub fn try_run(cmd: &mut Command) -> bool {
|
||||
let status = match cmd.status() {
|
||||
Ok(status) => status,
|
||||
Err(e) => fail(&format!(
|
||||
"failed to execute command: {:?}\nerror: {}",
|
||||
cmd, e
|
||||
)),
|
||||
Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
|
||||
};
|
||||
if !status.success() {
|
||||
println!(
|
||||
|
@ -88,10 +85,7 @@ pub fn run_suppressed(cmd: &mut Command) {
|
|||
pub fn try_run_suppressed(cmd: &mut Command) -> bool {
|
||||
let output = match cmd.output() {
|
||||
Ok(status) => status,
|
||||
Err(e) => fail(&format!(
|
||||
"failed to execute command: {:?}\nerror: {}",
|
||||
cmd, e
|
||||
)),
|
||||
Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
|
||||
};
|
||||
if !output.status.success() {
|
||||
println!(
|
||||
|
@ -119,8 +113,10 @@ pub fn gnu_target(target: &str) -> &str {
|
|||
}
|
||||
|
||||
pub fn make(host: &str) -> PathBuf {
|
||||
if host.contains("dragonfly") || host.contains("freebsd")
|
||||
|| host.contains("netbsd") || host.contains("openbsd")
|
||||
if host.contains("dragonfly")
|
||||
|| host.contains("freebsd")
|
||||
|| host.contains("netbsd")
|
||||
|| host.contains("openbsd")
|
||||
{
|
||||
PathBuf::from("gmake")
|
||||
} else {
|
||||
|
@ -131,10 +127,7 @@ pub fn make(host: &str) -> PathBuf {
|
|||
pub fn output(cmd: &mut Command) -> String {
|
||||
let output = match cmd.stderr(Stdio::inherit()).output() {
|
||||
Ok(status) => status,
|
||||
Err(e) => fail(&format!(
|
||||
"failed to execute command: {:?}\nerror: {}",
|
||||
cmd, e
|
||||
)),
|
||||
Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
|
||||
};
|
||||
if !output.status.success() {
|
||||
panic!(
|
||||
|
@ -147,7 +140,8 @@ pub fn output(cmd: &mut Command) -> String {
|
|||
}
|
||||
|
||||
pub fn rerun_if_changed_anything_in_dir(dir: &Path) {
|
||||
let mut stack = dir.read_dir()
|
||||
let mut stack = dir
|
||||
.read_dir()
|
||||
.unwrap()
|
||||
.map(|e| e.unwrap())
|
||||
.filter(|e| &*e.file_name() != ".git")
|
||||
|
@ -164,9 +158,7 @@ pub fn rerun_if_changed_anything_in_dir(dir: &Path) {
|
|||
|
||||
/// Returns the last-modified time for `path`, or zero if it doesn't exist.
|
||||
pub fn mtime(path: &Path) -> SystemTime {
|
||||
fs::metadata(path)
|
||||
.and_then(|f| f.modified())
|
||||
.unwrap_or(UNIX_EPOCH)
|
||||
fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH)
|
||||
}
|
||||
|
||||
/// Returns `true` if `dst` is up to date given that the file or files in `src`
|
||||
|
@ -205,7 +197,7 @@ impl NativeLibBoilerplate {
|
|||
/// ensure it's linked against correctly.
|
||||
pub fn fixup_sanitizer_lib_name(&self, sanitizer_name: &str) {
|
||||
if env::var("TARGET").unwrap() != "x86_64-apple-darwin" {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
let dir = self.out_dir.join("build/lib/darwin");
|
||||
|
@ -248,8 +240,8 @@ pub fn native_lib_boilerplate(
|
|||
) -> Result<NativeLibBoilerplate, ()> {
|
||||
rerun_if_changed_anything_in_dir(src_dir);
|
||||
|
||||
let out_dir = env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or_else(||
|
||||
env::var_os("OUT_DIR").unwrap());
|
||||
let out_dir =
|
||||
env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or_else(|| env::var_os("OUT_DIR").unwrap());
|
||||
let out_dir = PathBuf::from(out_dir).join(out_name);
|
||||
t!(fs::create_dir_all(&out_dir));
|
||||
if link_name.contains('=') {
|
||||
|
@ -257,36 +249,26 @@ pub fn native_lib_boilerplate(
|
|||
} else {
|
||||
println!("cargo:rustc-link-lib=static={}", link_name);
|
||||
}
|
||||
println!(
|
||||
"cargo:rustc-link-search=native={}",
|
||||
out_dir.join(search_subdir).display()
|
||||
);
|
||||
println!("cargo:rustc-link-search=native={}", out_dir.join(search_subdir).display());
|
||||
|
||||
let timestamp = out_dir.join("rustbuild.timestamp");
|
||||
if !up_to_date(Path::new("build.rs"), ×tamp) || !up_to_date(src_dir, ×tamp) {
|
||||
Ok(NativeLibBoilerplate {
|
||||
src_dir: src_dir.to_path_buf(),
|
||||
out_dir,
|
||||
})
|
||||
Ok(NativeLibBoilerplate { src_dir: src_dir.to_path_buf(), out_dir })
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sanitizer_lib_boilerplate(sanitizer_name: &str)
|
||||
-> Result<(NativeLibBoilerplate, String), ()>
|
||||
{
|
||||
pub fn sanitizer_lib_boilerplate(
|
||||
sanitizer_name: &str,
|
||||
) -> Result<(NativeLibBoilerplate, String), ()> {
|
||||
let (link_name, search_path, apple) = match &*env::var("TARGET").unwrap() {
|
||||
"x86_64-unknown-linux-gnu" => (
|
||||
format!("clang_rt.{}-x86_64", sanitizer_name),
|
||||
"build/lib/linux",
|
||||
false,
|
||||
),
|
||||
"x86_64-apple-darwin" => (
|
||||
format!("clang_rt.{}_osx_dynamic", sanitizer_name),
|
||||
"build/lib/darwin",
|
||||
true,
|
||||
),
|
||||
"x86_64-unknown-linux-gnu" => {
|
||||
(format!("clang_rt.{}-x86_64", sanitizer_name), "build/lib/linux", false)
|
||||
}
|
||||
"x86_64-apple-darwin" => {
|
||||
(format!("clang_rt.{}_osx_dynamic", sanitizer_name), "build/lib/darwin", true)
|
||||
}
|
||||
_ => return Err(()),
|
||||
};
|
||||
let to_link = if apple {
|
||||
|
@ -297,12 +279,7 @@ pub fn sanitizer_lib_boilerplate(sanitizer_name: &str)
|
|||
// This env var is provided by rustbuild to tell us where `compiler-rt`
|
||||
// lives.
|
||||
let dir = env::var_os("RUST_COMPILER_RT_ROOT").unwrap();
|
||||
let lib = native_lib_boilerplate(
|
||||
dir.as_ref(),
|
||||
sanitizer_name,
|
||||
&to_link,
|
||||
search_path,
|
||||
)?;
|
||||
let lib = native_lib_boilerplate(dir.as_ref(), sanitizer_name, &to_link, search_path)?;
|
||||
Ok((lib, link_name))
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
mod _common;
|
||||
|
||||
use std::char;
|
||||
use _common::validate;
|
||||
use std::char;
|
||||
|
||||
fn main() {
|
||||
for n in 0..10 {
|
||||
|
|
|
@ -2,10 +2,10 @@ extern crate rand;
|
|||
|
||||
mod _common;
|
||||
|
||||
use std::char;
|
||||
use rand::{IsaacRng, Rng, SeedableRng};
|
||||
use rand::distributions::{Range, Sample};
|
||||
use _common::{validate, SEED};
|
||||
use rand::distributions::{Range, Sample};
|
||||
use rand::{IsaacRng, Rng, SeedableRng};
|
||||
use std::char;
|
||||
|
||||
fn main() {
|
||||
let mut rnd = IsaacRng::from_seed(&SEED);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
mod _common;
|
||||
|
||||
use std::mem::transmute;
|
||||
use _common::validate;
|
||||
use std::mem::transmute;
|
||||
|
||||
fn main() {
|
||||
for bits in 0u32..(1 << 21) {
|
||||
|
|
|
@ -24,10 +24,7 @@ extern "Rust" {
|
|||
#[rustc_allocator_nounwind]
|
||||
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
|
||||
#[rustc_allocator_nounwind]
|
||||
fn __rust_realloc(ptr: *mut u8,
|
||||
old_size: usize,
|
||||
align: usize,
|
||||
new_size: usize) -> *mut u8;
|
||||
fn __rust_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8;
|
||||
#[rustc_allocator_nounwind]
|
||||
fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
|
||||
}
|
||||
|
@ -178,12 +175,12 @@ unsafe impl Alloc for Global {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn realloc(&mut self,
|
||||
ptr: NonNull<u8>,
|
||||
layout: Layout,
|
||||
new_size: usize)
|
||||
-> Result<NonNull<u8>, AllocErr>
|
||||
{
|
||||
unsafe fn realloc(
|
||||
&mut self,
|
||||
ptr: NonNull<u8>,
|
||||
layout: Layout,
|
||||
new_size: usize,
|
||||
) -> Result<NonNull<u8>, AllocErr> {
|
||||
NonNull::new(realloc(ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
|
||||
}
|
||||
|
||||
|
@ -204,11 +201,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
|
|||
} else {
|
||||
let layout = Layout::from_size_align_unchecked(size, align);
|
||||
let ptr = alloc(layout);
|
||||
if !ptr.is_null() {
|
||||
ptr
|
||||
} else {
|
||||
handle_alloc_error(layout)
|
||||
}
|
||||
if !ptr.is_null() { ptr } else { handle_alloc_error(layout) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ extern crate test;
|
|||
|
||||
mod btree;
|
||||
mod linked_list;
|
||||
mod string;
|
||||
mod str;
|
||||
mod slice;
|
||||
mod str;
|
||||
mod string;
|
||||
mod vec;
|
||||
mod vec_deque;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use std::iter::{repeat, FromIterator};
|
||||
use test::Bencher;
|
||||
use std::iter::{FromIterator, repeat};
|
||||
|
||||
#[bench]
|
||||
fn bench_new(b: &mut Bencher) {
|
||||
|
|
|
@ -16,8 +16,9 @@ use Cow::*;
|
|||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B>
|
||||
where B: ToOwned,
|
||||
<B as ToOwned>::Owned: 'a
|
||||
where
|
||||
B: ToOwned,
|
||||
<B as ToOwned>::Owned: 'a,
|
||||
{
|
||||
fn borrow(&self) -> &B {
|
||||
&**self
|
||||
|
@ -69,9 +70,7 @@ pub trait ToOwned {
|
|||
/// let mut v: Vec<i32> = Vec::new();
|
||||
/// [1, 2][..].clone_into(&mut v);
|
||||
/// ```
|
||||
#[unstable(feature = "toowned_clone_into",
|
||||
reason = "recently added",
|
||||
issue = "41263")]
|
||||
#[unstable(feature = "toowned_clone_into", reason = "recently added", issue = "41263")]
|
||||
fn clone_into(&self, target: &mut Self::Owned) {
|
||||
*target = self.to_owned();
|
||||
}
|
||||
|
@ -79,7 +78,8 @@ pub trait ToOwned {
|
|||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> ToOwned for T
|
||||
where T: Clone
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
type Owned = T;
|
||||
fn to_owned(&self) -> T {
|
||||
|
@ -169,17 +169,16 @@ impl<T> ToOwned for T
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub enum Cow<'a, B: ?Sized + 'a>
|
||||
where B: ToOwned
|
||||
where
|
||||
B: ToOwned,
|
||||
{
|
||||
/// Borrowed data.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Borrowed(#[stable(feature = "rust1", since = "1.0.0")]
|
||||
&'a B),
|
||||
Borrowed(#[stable(feature = "rust1", since = "1.0.0")] &'a B),
|
||||
|
||||
/// Owned data.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Owned(#[stable(feature = "rust1", since = "1.0.0")]
|
||||
<B as ToOwned>::Owned),
|
||||
Owned(#[stable(feature = "rust1", since = "1.0.0")] <B as ToOwned>::Owned),
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -335,7 +334,8 @@ impl<B: ?Sized> Eq for Cow<'_, B> where B: Eq + ToOwned {}
|
|||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<B: ?Sized> Ord for Cow<'_, B>
|
||||
where B: Ord + ToOwned
|
||||
where
|
||||
B: Ord + ToOwned,
|
||||
{
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
|
@ -345,8 +345,9 @@ impl<B: ?Sized> Ord for Cow<'_, B>
|
|||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B>
|
||||
where B: PartialEq<C> + ToOwned,
|
||||
C: ToOwned
|
||||
where
|
||||
B: PartialEq<C> + ToOwned,
|
||||
C: ToOwned,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &Cow<'b, C>) -> bool {
|
||||
|
@ -356,7 +357,8 @@ impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B>
|
|||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B>
|
||||
where B: PartialOrd + ToOwned
|
||||
where
|
||||
B: PartialOrd + ToOwned,
|
||||
{
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
|
||||
|
@ -403,7 +405,8 @@ where
|
|||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<B: ?Sized> Hash for Cow<'_, B>
|
||||
where B: Hash + ToOwned
|
||||
where
|
||||
B: Hash + ToOwned,
|
||||
{
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
|
|
|
@ -134,21 +134,21 @@ use core::convert::{From, TryFrom};
|
|||
use core::fmt;
|
||||
use core::future::Future;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::iter::{Iterator, FromIterator, FusedIterator};
|
||||
use core::iter::{FromIterator, FusedIterator, Iterator};
|
||||
use core::marker::{Unpin, Unsize};
|
||||
use core::mem;
|
||||
use core::pin::Pin;
|
||||
use core::ops::{
|
||||
CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Receiver, Generator, GeneratorState
|
||||
CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Generator, GeneratorState, Receiver,
|
||||
};
|
||||
use core::pin::Pin;
|
||||
use core::ptr::{self, NonNull, Unique};
|
||||
use core::slice;
|
||||
use core::task::{Context, Poll};
|
||||
|
||||
use crate::alloc::{self, Global, Alloc};
|
||||
use crate::vec::Vec;
|
||||
use crate::alloc::{self, Alloc, Global};
|
||||
use crate::raw_vec::RawVec;
|
||||
use crate::str::from_boxed_utf8_unchecked;
|
||||
use crate::vec::Vec;
|
||||
|
||||
/// A pointer type for heap allocation.
|
||||
///
|
||||
|
@ -196,12 +196,10 @@ impl<T> Box<T> {
|
|||
pub fn new_uninit() -> Box<mem::MaybeUninit<T>> {
|
||||
let layout = alloc::Layout::new::<mem::MaybeUninit<T>>();
|
||||
if layout.size() == 0 {
|
||||
return Box(NonNull::dangling().into())
|
||||
return Box(NonNull::dangling().into());
|
||||
}
|
||||
let ptr = unsafe {
|
||||
Global.alloc(layout)
|
||||
.unwrap_or_else(|_| alloc::handle_alloc_error(layout))
|
||||
};
|
||||
let ptr =
|
||||
unsafe { Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)) };
|
||||
Box(ptr.cast().into())
|
||||
}
|
||||
|
||||
|
@ -269,9 +267,7 @@ impl<T> Box<[T]> {
|
|||
NonNull::dangling()
|
||||
} else {
|
||||
unsafe {
|
||||
Global.alloc(layout)
|
||||
.unwrap_or_else(|_| alloc::handle_alloc_error(layout))
|
||||
.cast()
|
||||
Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).cast()
|
||||
}
|
||||
};
|
||||
let slice = unsafe { slice::from_raw_parts_mut(ptr.as_ptr(), len) };
|
||||
|
@ -532,7 +528,7 @@ impl<T: ?Sized> Box<T> {
|
|||
#[inline]
|
||||
pub fn leak<'a>(b: Box<T>) -> &'a mut T
|
||||
where
|
||||
T: 'a // Technically not needed, but kept to be explicit.
|
||||
T: 'a, // Technically not needed, but kept to be explicit.
|
||||
{
|
||||
unsafe { &mut *Box::into_raw(b) }
|
||||
}
|
||||
|
@ -625,15 +621,12 @@ impl<T: Clone> Clone for Box<T> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[stable(feature = "box_slice_clone", since = "1.3.0")]
|
||||
impl Clone for Box<str> {
|
||||
fn clone(&self) -> Self {
|
||||
// this makes a copy of the data
|
||||
let buf: Box<[u8]> = self.as_bytes().into();
|
||||
unsafe {
|
||||
from_boxed_utf8_unchecked(buf)
|
||||
}
|
||||
unsafe { from_boxed_utf8_unchecked(buf) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1053,10 +1046,7 @@ impl<A> FromIterator<A> for Box<[A]> {
|
|||
#[stable(feature = "box_slice_clone", since = "1.3.0")]
|
||||
impl<T: Clone> Clone for Box<[T]> {
|
||||
fn clone(&self) -> Self {
|
||||
let mut new = BoxBuilder {
|
||||
data: RawVec::with_capacity(self.len()),
|
||||
len: 0,
|
||||
};
|
||||
let mut new = BoxBuilder { data: RawVec::with_capacity(self.len()), len: 0 };
|
||||
|
||||
let mut target = new.data.ptr();
|
||||
|
||||
|
@ -1152,7 +1142,7 @@ impl<T: ?Sized> AsMut<T> for Box<T> {
|
|||
* could have a method to project a Pin<T> from it.
|
||||
*/
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<T: ?Sized> Unpin for Box<T> { }
|
||||
impl<T: ?Sized> Unpin for Box<T> {}
|
||||
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
impl<G: ?Sized + Generator + Unpin> Generator for Box<G> {
|
||||
|
|
|
@ -145,11 +145,11 @@
|
|||
#![allow(missing_docs)]
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::iter::{FromIterator, FusedIterator, TrustedLen};
|
||||
use core::mem::{swap, size_of, ManuallyDrop};
|
||||
use core::ptr;
|
||||
use core::fmt;
|
||||
use core::iter::{FromIterator, FusedIterator, TrustedLen};
|
||||
use core::mem::{size_of, swap, ManuallyDrop};
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::ptr;
|
||||
|
||||
use crate::slice;
|
||||
use crate::vec::{self, Vec};
|
||||
|
@ -267,9 +267,7 @@ pub struct PeekMut<'a, T: 'a + Ord> {
|
|||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: Ord + fmt::Debug> fmt::Debug for PeekMut<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("PeekMut")
|
||||
.field(&self.heap.data[0])
|
||||
.finish()
|
||||
f.debug_tuple("PeekMut").field(&self.heap.data[0]).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -404,14 +402,7 @@ impl<T: Ord> BinaryHeap<T> {
|
|||
/// Cost is O(1) in the worst case.
|
||||
#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
|
||||
pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T>> {
|
||||
if self.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(PeekMut {
|
||||
heap: self,
|
||||
sift: true,
|
||||
})
|
||||
}
|
||||
if self.is_empty() { None } else { Some(PeekMut { heap: self, sift: true }) }
|
||||
}
|
||||
|
||||
/// Removes the greatest item from the binary heap and returns it, or `None` if it
|
||||
|
@ -674,9 +665,7 @@ impl<T: Ord> BinaryHeap<T> {
|
|||
#[inline]
|
||||
#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
|
||||
pub fn drain_sorted(&mut self) -> DrainSorted<'_, T> {
|
||||
DrainSorted {
|
||||
inner: self,
|
||||
}
|
||||
DrainSorted { inner: self }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -718,9 +707,7 @@ impl<T> BinaryHeap<T> {
|
|||
/// ```
|
||||
#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
|
||||
pub fn into_iter_sorted(self) -> IntoIterSorted<T> {
|
||||
IntoIterSorted {
|
||||
inner: self,
|
||||
}
|
||||
IntoIterSorted { inner: self }
|
||||
}
|
||||
|
||||
/// Returns the greatest item in the binary heap, or `None` if it is empty.
|
||||
|
@ -857,7 +844,7 @@ impl<T> BinaryHeap<T> {
|
|||
/// assert!(heap.capacity() >= 10);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "shrink_to", reason = "new API", issue="56431")]
|
||||
#[unstable(feature = "shrink_to", reason = "new API", issue = "56431")]
|
||||
pub fn shrink_to(&mut self, min_capacity: usize) {
|
||||
self.data.shrink_to(min_capacity)
|
||||
}
|
||||
|
@ -991,11 +978,7 @@ impl<'a, T> Hole<'a, T> {
|
|||
debug_assert!(pos < data.len());
|
||||
// SAFE: pos should be inside the slice
|
||||
let elt = ptr::read(data.get_unchecked(pos));
|
||||
Hole {
|
||||
data,
|
||||
elt: ManuallyDrop::new(elt),
|
||||
pos,
|
||||
}
|
||||
Hole { data, elt: ManuallyDrop::new(elt), pos }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -1059,9 +1042,7 @@ pub struct Iter<'a, T: 'a> {
|
|||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Iter")
|
||||
.field(&self.iter.as_slice())
|
||||
.finish()
|
||||
f.debug_tuple("Iter").field(&self.iter.as_slice()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1127,9 +1108,7 @@ pub struct 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()
|
||||
f.debug_tuple("IntoIter").field(&self.iter.as_slice()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1281,7 +1260,7 @@ impl<T: Ord> Iterator for DrainSorted<'_, T> {
|
|||
}
|
||||
|
||||
#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
|
||||
impl<T: Ord> ExactSizeIterator for DrainSorted<'_, T> { }
|
||||
impl<T: Ord> ExactSizeIterator for DrainSorted<'_, T> {}
|
||||
|
||||
#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
|
||||
impl<T: Ord> FusedIterator for DrainSorted<'_, T> {}
|
||||
|
|
|
@ -2,17 +2,17 @@ use core::borrow::Borrow;
|
|||
use core::cmp::Ordering;
|
||||
use core::fmt::Debug;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::iter::{FromIterator, Peekable, FusedIterator};
|
||||
use core::iter::{FromIterator, FusedIterator, Peekable};
|
||||
use core::marker::PhantomData;
|
||||
use core::ops::Bound::{Excluded, Included, Unbounded};
|
||||
use core::ops::{Index, RangeBounds};
|
||||
use core::{fmt, intrinsics, mem, ptr};
|
||||
|
||||
use super::node::{self, Handle, NodeRef, marker, InsertResult::*, ForceResult::*};
|
||||
use super::node::{self, marker, ForceResult::*, Handle, InsertResult::*, NodeRef};
|
||||
use super::search::{self, SearchResult::*};
|
||||
|
||||
use UnderflowResult::*;
|
||||
use Entry::*;
|
||||
use UnderflowResult::*;
|
||||
|
||||
/// A map based on a B-Tree.
|
||||
///
|
||||
|
@ -138,16 +138,15 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for BTreeMap<K, V> {
|
|||
impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
|
||||
fn clone(&self) -> BTreeMap<K, V> {
|
||||
fn clone_subtree<'a, K: Clone, V: Clone>(
|
||||
node: node::NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>
|
||||
node: node::NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>,
|
||||
) -> BTreeMap<K, V>
|
||||
where K: 'a, V: 'a,
|
||||
where
|
||||
K: 'a,
|
||||
V: 'a,
|
||||
{
|
||||
match node.force() {
|
||||
Leaf(leaf) => {
|
||||
let mut out_tree = BTreeMap {
|
||||
root: node::Root::new_leaf(),
|
||||
length: 0,
|
||||
};
|
||||
let mut out_tree = BTreeMap { root: node::Root::new_leaf(), length: 0 };
|
||||
|
||||
{
|
||||
let mut out_node = match out_tree.root.as_mut().force() {
|
||||
|
@ -203,10 +202,7 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
|
|||
if self.is_empty() {
|
||||
// Ideally we'd call `BTreeMap::new` here, but that has the `K:
|
||||
// Ord` constraint, which this method lacks.
|
||||
BTreeMap {
|
||||
root: node::Root::shared_empty_root(),
|
||||
length: 0,
|
||||
}
|
||||
BTreeMap { root: node::Root::shared_empty_root(), length: 0 }
|
||||
} else {
|
||||
clone_subtree(self.root.as_ref())
|
||||
}
|
||||
|
@ -214,8 +210,9 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
|
|||
}
|
||||
|
||||
impl<K, Q: ?Sized> super::Recover<Q> for BTreeMap<K, ()>
|
||||
where K: Borrow<Q> + Ord,
|
||||
Q: Ord
|
||||
where
|
||||
K: Borrow<Q> + Ord,
|
||||
Q: Ord,
|
||||
{
|
||||
type Key = K;
|
||||
|
||||
|
@ -228,15 +225,11 @@ impl<K, Q: ?Sized> super::Recover<Q> for BTreeMap<K, ()>
|
|||
|
||||
fn take(&mut self, key: &Q) -> Option<K> {
|
||||
match search::search_tree(self.root.as_mut(), key) {
|
||||
Found(handle) => {
|
||||
Some(OccupiedEntry {
|
||||
handle,
|
||||
length: &mut self.length,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
.remove_kv()
|
||||
.0)
|
||||
}
|
||||
Found(handle) => Some(
|
||||
OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData }
|
||||
.remove_kv()
|
||||
.0,
|
||||
),
|
||||
GoDown(_) => None,
|
||||
}
|
||||
}
|
||||
|
@ -246,13 +239,8 @@ impl<K, Q: ?Sized> super::Recover<Q> for BTreeMap<K, ()>
|
|||
match search::search_tree::<marker::Mut<'_>, K, (), K>(self.root.as_mut(), &key) {
|
||||
Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)),
|
||||
GoDown(handle) => {
|
||||
VacantEntry {
|
||||
key,
|
||||
handle,
|
||||
length: &mut self.length,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
.insert(());
|
||||
VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData }
|
||||
.insert(());
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -310,10 +298,7 @@ pub struct IntoIter<K, V> {
|
|||
#[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(),
|
||||
};
|
||||
let range = Range { front: self.front.reborrow(), back: self.back.reborrow() };
|
||||
f.debug_list().entries(range).finish()
|
||||
}
|
||||
}
|
||||
|
@ -408,10 +393,7 @@ pub struct RangeMut<'a, K: 'a, V: 'a> {
|
|||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for RangeMut<'_, K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let range = Range {
|
||||
front: self.front.reborrow(),
|
||||
back: self.back.reborrow(),
|
||||
};
|
||||
let range = Range { front: self.front.reborrow(), back: self.back.reborrow() };
|
||||
f.debug_list().entries(range).finish()
|
||||
}
|
||||
}
|
||||
|
@ -426,25 +408,19 @@ impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for RangeMut<'_, K, V> {
|
|||
pub enum Entry<'a, K: 'a, V: 'a> {
|
||||
/// A vacant entry.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Vacant(#[stable(feature = "rust1", since = "1.0.0")]
|
||||
VacantEntry<'a, K, V>),
|
||||
Vacant(#[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V>),
|
||||
|
||||
/// An occupied entry.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Occupied(#[stable(feature = "rust1", since = "1.0.0")]
|
||||
OccupiedEntry<'a, K, V>),
|
||||
Occupied(#[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V>),
|
||||
}
|
||||
|
||||
#[stable(feature= "debug_btree_map", since = "1.12.0")]
|
||||
#[stable(feature = "debug_btree_map", since = "1.12.0")]
|
||||
impl<K: Debug + Ord, V: Debug> Debug for Entry<'_, K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
Vacant(ref v) => f.debug_tuple("Entry")
|
||||
.field(v)
|
||||
.finish(),
|
||||
Occupied(ref o) => f.debug_tuple("Entry")
|
||||
.field(o)
|
||||
.finish(),
|
||||
Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
|
||||
Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -463,12 +439,10 @@ pub struct VacantEntry<'a, K: 'a, V: 'a> {
|
|||
_marker: PhantomData<&'a mut (K, V)>,
|
||||
}
|
||||
|
||||
#[stable(feature= "debug_btree_map", since = "1.12.0")]
|
||||
#[stable(feature = "debug_btree_map", since = "1.12.0")]
|
||||
impl<K: Debug + Ord, V> Debug for VacantEntry<'_, K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("VacantEntry")
|
||||
.field(self.key())
|
||||
.finish()
|
||||
f.debug_tuple("VacantEntry").field(self.key()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -486,13 +460,10 @@ pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
|
|||
_marker: PhantomData<&'a mut (K, V)>,
|
||||
}
|
||||
|
||||
#[stable(feature= "debug_btree_map", since = "1.12.0")]
|
||||
#[stable(feature = "debug_btree_map", since = "1.12.0")]
|
||||
impl<K: Debug + Ord, V: Debug> Debug for OccupiedEntry<'_, K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("OccupiedEntry")
|
||||
.field("key", self.key())
|
||||
.field("value", self.get())
|
||||
.finish()
|
||||
f.debug_struct("OccupiedEntry").field("key", self.key()).field("value", self.get()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -519,10 +490,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn new() -> BTreeMap<K, V> {
|
||||
BTreeMap {
|
||||
root: node::Root::shared_empty_root(),
|
||||
length: 0,
|
||||
}
|
||||
BTreeMap { root: node::Root::shared_empty_root(), length: 0 }
|
||||
}
|
||||
|
||||
/// Clears the map, removing all values.
|
||||
|
@ -563,8 +531,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
|
||||
where K: Borrow<Q>,
|
||||
Q: Ord
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
Q: Ord,
|
||||
{
|
||||
match search::search_tree(self.root.as_ref(), key) {
|
||||
Found(handle) => Some(handle.into_kv().1),
|
||||
|
@ -589,8 +558,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
/// ```
|
||||
#[stable(feature = "map_get_key_value", since = "1.40.0")]
|
||||
pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
|
||||
where K: Borrow<Q>,
|
||||
Q: Ord
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
Q: Ord,
|
||||
{
|
||||
match search::search_tree(self.root.as_ref(), k) {
|
||||
Found(handle) => Some(handle.into_kv()),
|
||||
|
@ -617,7 +587,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
/// ```
|
||||
#[unstable(feature = "map_first_last", issue = "62924")]
|
||||
pub fn first_key_value<T: ?Sized>(&self) -> Option<(&K, &V)>
|
||||
where T: Ord, K: Borrow<T>
|
||||
where
|
||||
T: Ord,
|
||||
K: Borrow<T>,
|
||||
{
|
||||
let front = first_leaf_edge(self.root.as_ref());
|
||||
front.right_kv().ok().map(Handle::into_kv)
|
||||
|
@ -644,15 +616,17 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
/// ```
|
||||
#[unstable(feature = "map_first_last", issue = "62924")]
|
||||
pub fn first_entry<T: ?Sized>(&mut self) -> Option<OccupiedEntry<'_, K, V>>
|
||||
where T: Ord, K: Borrow<T>
|
||||
where
|
||||
T: Ord,
|
||||
K: Borrow<T>,
|
||||
{
|
||||
match self.length {
|
||||
0 => None,
|
||||
_ => Some(OccupiedEntry {
|
||||
handle: self.root.as_mut().first_kv(),
|
||||
length: &mut self.length,
|
||||
_marker: PhantomData,
|
||||
}),
|
||||
handle: self.root.as_mut().first_kv(),
|
||||
length: &mut self.length,
|
||||
_marker: PhantomData,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -674,7 +648,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
/// ```
|
||||
#[unstable(feature = "map_first_last", issue = "62924")]
|
||||
pub fn last_key_value<T: ?Sized>(&self) -> Option<(&K, &V)>
|
||||
where T: Ord, K: Borrow<T>
|
||||
where
|
||||
T: Ord,
|
||||
K: Borrow<T>,
|
||||
{
|
||||
let back = last_leaf_edge(self.root.as_ref());
|
||||
back.left_kv().ok().map(Handle::into_kv)
|
||||
|
@ -701,15 +677,17 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
/// ```
|
||||
#[unstable(feature = "map_first_last", issue = "62924")]
|
||||
pub fn last_entry<T: ?Sized>(&mut self) -> Option<OccupiedEntry<'_, K, V>>
|
||||
where T: Ord, K: Borrow<T>
|
||||
where
|
||||
T: Ord,
|
||||
K: Borrow<T>,
|
||||
{
|
||||
match self.length {
|
||||
0 => None,
|
||||
_ => Some(OccupiedEntry {
|
||||
handle: self.root.as_mut().last_kv(),
|
||||
length: &mut self.length,
|
||||
_marker: PhantomData,
|
||||
}),
|
||||
handle: self.root.as_mut().last_kv(),
|
||||
length: &mut self.length,
|
||||
_marker: PhantomData,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -732,8 +710,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
|
||||
where K: Borrow<Q>,
|
||||
Q: Ord
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
Q: Ord,
|
||||
{
|
||||
self.get(key).is_some()
|
||||
}
|
||||
|
@ -760,8 +739,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
// See `get` for implementation notes, this is basically a copy-paste with mut's added
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V>
|
||||
where K: Borrow<Q>,
|
||||
Q: Ord
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
Q: Ord,
|
||||
{
|
||||
match search::search_tree(self.root.as_mut(), key) {
|
||||
Found(handle) => Some(handle.into_kv_mut().1),
|
||||
|
@ -826,18 +806,14 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
|
||||
where K: Borrow<Q>,
|
||||
Q: Ord
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
Q: Ord,
|
||||
{
|
||||
match search::search_tree(self.root.as_mut(), key) {
|
||||
Found(handle) => {
|
||||
Some(OccupiedEntry {
|
||||
handle,
|
||||
length: &mut self.length,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
.remove())
|
||||
}
|
||||
Found(handle) => Some(
|
||||
OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData }.remove(),
|
||||
),
|
||||
GoDown(_) => None,
|
||||
}
|
||||
}
|
||||
|
@ -886,10 +862,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
// First, we merge `self` and `other` into a sorted sequence in linear time.
|
||||
let self_iter = mem::take(self).into_iter();
|
||||
let other_iter = mem::take(other).into_iter();
|
||||
let iter = MergeIter {
|
||||
left: self_iter.peekable(),
|
||||
right: other_iter.peekable(),
|
||||
};
|
||||
let iter = MergeIter { left: self_iter.peekable(), right: other_iter.peekable() };
|
||||
|
||||
// Second, we build a tree from the sorted sequence in linear time.
|
||||
self.from_sorted_iter(iter);
|
||||
|
@ -927,13 +900,16 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
/// ```
|
||||
#[stable(feature = "btree_range", since = "1.17.0")]
|
||||
pub fn range<T: ?Sized, R>(&self, range: R) -> Range<'_, K, V>
|
||||
where T: Ord, K: Borrow<T>, R: RangeBounds<T>
|
||||
where
|
||||
T: Ord,
|
||||
K: Borrow<T>,
|
||||
R: RangeBounds<T>,
|
||||
{
|
||||
let root1 = self.root.as_ref();
|
||||
let root2 = self.root.as_ref();
|
||||
let (f, b) = range_search(root1, root2, range);
|
||||
|
||||
Range { front: f, back: b}
|
||||
Range { front: f, back: b }
|
||||
}
|
||||
|
||||
/// Constructs a mutable double-ended iterator over a sub-range of elements in the map.
|
||||
|
@ -968,17 +944,16 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
/// ```
|
||||
#[stable(feature = "btree_range", since = "1.17.0")]
|
||||
pub fn range_mut<T: ?Sized, R>(&mut self, range: R) -> RangeMut<'_, K, V>
|
||||
where T: Ord, K: Borrow<T>, R: RangeBounds<T>
|
||||
where
|
||||
T: Ord,
|
||||
K: Borrow<T>,
|
||||
R: RangeBounds<T>,
|
||||
{
|
||||
let root1 = self.root.as_mut();
|
||||
let root2 = unsafe { ptr::read(&root1) };
|
||||
let (f, b) = range_search(root1, root2, range);
|
||||
|
||||
RangeMut {
|
||||
front: f,
|
||||
back: b,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
RangeMut { front: f, back: b, _marker: PhantomData }
|
||||
}
|
||||
|
||||
/// Gets the given key's corresponding entry in the map for in-place manipulation.
|
||||
|
@ -1005,19 +980,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
self.ensure_root_is_owned();
|
||||
match search::search_tree(self.root.as_mut(), &key) {
|
||||
Found(handle) => {
|
||||
Occupied(OccupiedEntry {
|
||||
handle,
|
||||
length: &mut self.length,
|
||||
_marker: PhantomData,
|
||||
})
|
||||
Occupied(OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData })
|
||||
}
|
||||
GoDown(handle) => {
|
||||
Vacant(VacantEntry {
|
||||
key,
|
||||
handle,
|
||||
length: &mut self.length,
|
||||
_marker: PhantomData,
|
||||
})
|
||||
Vacant(VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1124,7 +1090,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
/// ```
|
||||
#[stable(feature = "btree_split_off", since = "1.11.0")]
|
||||
pub fn split_off<Q: ?Sized + Ord>(&mut self, key: &Q) -> Self
|
||||
where K: Borrow<Q>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
{
|
||||
if self.is_empty() {
|
||||
return Self::new();
|
||||
|
@ -1182,10 +1149,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
|
||||
/// Calculates the number of elements if it is incorrect.
|
||||
fn recalc_length(&mut self) {
|
||||
fn dfs<'a, K, V>(
|
||||
node: NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>
|
||||
) -> usize
|
||||
where K: 'a, V: 'a
|
||||
fn dfs<'a, K, V>(node: NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>) -> usize
|
||||
where
|
||||
K: 'a,
|
||||
V: 'a,
|
||||
{
|
||||
let mut res = node.len();
|
||||
|
||||
|
@ -1338,10 +1305,7 @@ impl<K, V> ExactSizeIterator for Iter<'_, K, V> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<K, V> Clone for Iter<'_, K, V> {
|
||||
fn clone(&self) -> Self {
|
||||
Iter {
|
||||
range: self.range.clone(),
|
||||
length: self.length,
|
||||
}
|
||||
Iter { range: self.range.clone(), length: self.length }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1410,11 +1374,7 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
|
|||
let len = self.length;
|
||||
mem::forget(self);
|
||||
|
||||
IntoIter {
|
||||
front: first_leaf_edge(root1),
|
||||
back: last_leaf_edge(root2),
|
||||
length: len,
|
||||
}
|
||||
IntoIter { front: first_leaf_edge(root1), back: last_leaf_edge(root2), length: len }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1619,11 +1579,7 @@ impl<'a, K, V> Iterator for Range<'a, K, V> {
|
|||
type Item = (&'a K, &'a V);
|
||||
|
||||
fn next(&mut self) -> Option<(&'a K, &'a V)> {
|
||||
if self.front == self.back {
|
||||
None
|
||||
} else {
|
||||
unsafe { Some(self.next_unchecked()) }
|
||||
}
|
||||
if self.front == self.back { None } else { unsafe { Some(self.next_unchecked()) } }
|
||||
}
|
||||
|
||||
fn last(mut self) -> Option<(&'a K, &'a V)> {
|
||||
|
@ -1700,11 +1656,7 @@ impl<'a, K, V> Range<'a, K, V> {
|
|||
#[stable(feature = "btree_range", since = "1.17.0")]
|
||||
impl<'a, K, V> DoubleEndedIterator for Range<'a, K, V> {
|
||||
fn next_back(&mut self) -> Option<(&'a K, &'a V)> {
|
||||
if self.front == self.back {
|
||||
None
|
||||
} else {
|
||||
unsafe { Some(self.next_back_unchecked()) }
|
||||
}
|
||||
if self.front == self.back { None } else { unsafe { Some(self.next_back_unchecked()) } }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1746,10 +1698,7 @@ impl<K, V> FusedIterator for Range<'_, K, V> {}
|
|||
#[stable(feature = "btree_range", since = "1.17.0")]
|
||||
impl<K, V> Clone for Range<'_, K, V> {
|
||||
fn clone(&self) -> Self {
|
||||
Range {
|
||||
front: self.front,
|
||||
back: self.back,
|
||||
}
|
||||
Range { front: self.front, back: self.back }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1758,11 +1707,7 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> {
|
|||
type Item = (&'a K, &'a mut V);
|
||||
|
||||
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
|
||||
if self.front == self.back {
|
||||
None
|
||||
} else {
|
||||
unsafe { Some(self.next_unchecked()) }
|
||||
}
|
||||
if self.front == self.back { None } else { unsafe { Some(self.next_unchecked()) } }
|
||||
}
|
||||
|
||||
fn last(mut self) -> Option<(&'a K, &'a mut V)> {
|
||||
|
@ -1809,11 +1754,7 @@ impl<'a, K, V> RangeMut<'a, K, V> {
|
|||
#[stable(feature = "btree_range", since = "1.17.0")]
|
||||
impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> {
|
||||
fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> {
|
||||
if self.front == self.back {
|
||||
None
|
||||
} else {
|
||||
unsafe { Some(self.next_back_unchecked()) }
|
||||
}
|
||||
if self.front == self.back { None } else { unsafe { Some(self.next_back_unchecked()) } }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1934,8 +1875,9 @@ impl<K: Debug, V: Debug> Debug for BTreeMap<K, V> {
|
|||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<K: Ord, Q: ?Sized, V> Index<&Q> for BTreeMap<K, V>
|
||||
where K: Borrow<Q>,
|
||||
Q: Ord
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
Q: Ord,
|
||||
{
|
||||
type Output = V;
|
||||
|
||||
|
@ -1950,9 +1892,9 @@ impl<K: Ord, Q: ?Sized, V> Index<&Q> for BTreeMap<K, V>
|
|||
}
|
||||
}
|
||||
|
||||
fn first_leaf_edge<BorrowType, K, V>
|
||||
(mut node: NodeRef<BorrowType, K, V, marker::LeafOrInternal>)
|
||||
-> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
|
||||
fn first_leaf_edge<BorrowType, K, V>(
|
||||
mut node: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
|
||||
) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
|
||||
loop {
|
||||
match node.force() {
|
||||
Leaf(leaf) => return leaf.first_edge(),
|
||||
|
@ -1963,9 +1905,9 @@ fn first_leaf_edge<BorrowType, K, V>
|
|||
}
|
||||
}
|
||||
|
||||
fn last_leaf_edge<BorrowType, K, V>
|
||||
(mut node: NodeRef<BorrowType, K, V, marker::LeafOrInternal>)
|
||||
-> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
|
||||
fn last_leaf_edge<BorrowType, K, V>(
|
||||
mut node: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
|
||||
) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
|
||||
loop {
|
||||
match node.force() {
|
||||
Leaf(leaf) => return leaf.last_edge(),
|
||||
|
@ -1979,20 +1921,28 @@ fn last_leaf_edge<BorrowType, K, V>
|
|||
fn range_search<BorrowType, K, V, Q: ?Sized, R: RangeBounds<Q>>(
|
||||
root1: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
|
||||
root2: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
|
||||
range: R
|
||||
)-> (Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
|
||||
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>)
|
||||
where Q: Ord, K: Borrow<Q>
|
||||
range: R,
|
||||
) -> (
|
||||
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
|
||||
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
|
||||
)
|
||||
where
|
||||
Q: Ord,
|
||||
K: Borrow<Q>,
|
||||
{
|
||||
match (range.start_bound(), range.end_bound()) {
|
||||
(Excluded(s), Excluded(e)) if s==e =>
|
||||
panic!("range start and end are equal and excluded in BTreeMap"),
|
||||
(Included(s), Included(e)) |
|
||||
(Included(s), Excluded(e)) |
|
||||
(Excluded(s), Included(e)) |
|
||||
(Excluded(s), Excluded(e)) if s>e =>
|
||||
panic!("range start is greater than range end in BTreeMap"),
|
||||
_ => {},
|
||||
(Excluded(s), Excluded(e)) if s == e => {
|
||||
panic!("range start and end are equal and excluded in BTreeMap")
|
||||
}
|
||||
(Included(s), Included(e))
|
||||
| (Included(s), Excluded(e))
|
||||
| (Excluded(s), Included(e))
|
||||
| (Excluded(s), Excluded(e))
|
||||
if s > e =>
|
||||
{
|
||||
panic!("range start is greater than range end in BTreeMap")
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
let mut min_node = root1;
|
||||
|
@ -2004,11 +1954,17 @@ fn range_search<BorrowType, K, V, Q: ?Sized, R: RangeBounds<Q>>(
|
|||
loop {
|
||||
let min_edge = match (min_found, range.start_bound()) {
|
||||
(false, Included(key)) => match search::search_linear(&min_node, key) {
|
||||
(i, true) => { min_found = true; i },
|
||||
(i, true) => {
|
||||
min_found = true;
|
||||
i
|
||||
}
|
||||
(i, false) => i,
|
||||
},
|
||||
(false, Excluded(key)) => match search::search_linear(&min_node, key) {
|
||||
(i, true) => { min_found = true; i+1 },
|
||||
(i, true) => {
|
||||
min_found = true;
|
||||
i + 1
|
||||
}
|
||||
(i, false) => i,
|
||||
},
|
||||
(_, Unbounded) => 0,
|
||||
|
@ -2018,11 +1974,17 @@ fn range_search<BorrowType, K, V, Q: ?Sized, R: RangeBounds<Q>>(
|
|||
|
||||
let max_edge = match (max_found, range.end_bound()) {
|
||||
(false, Included(key)) => match search::search_linear(&max_node, key) {
|
||||
(i, true) => { max_found = true; i+1 },
|
||||
(i, true) => {
|
||||
max_found = true;
|
||||
i + 1
|
||||
}
|
||||
(i, false) => i,
|
||||
},
|
||||
(false, Excluded(key)) => match search::search_linear(&max_node, key) {
|
||||
(i, true) => { max_found = true; i },
|
||||
(i, true) => {
|
||||
max_found = true;
|
||||
i
|
||||
}
|
||||
(i, false) => i,
|
||||
},
|
||||
(_, Unbounded) => max_node.keys().len(),
|
||||
|
@ -2031,8 +1993,12 @@ fn range_search<BorrowType, K, V, Q: ?Sized, R: RangeBounds<Q>>(
|
|||
};
|
||||
|
||||
if !diverged {
|
||||
if max_edge < min_edge { panic!("Ord is ill-defined in BTreeMap range") }
|
||||
if min_edge != max_edge { diverged = true; }
|
||||
if max_edge < min_edge {
|
||||
panic!("Ord is ill-defined in BTreeMap range")
|
||||
}
|
||||
if min_edge != max_edge {
|
||||
diverged = true;
|
||||
}
|
||||
}
|
||||
|
||||
let front = Handle::new_edge(min_node, min_edge);
|
||||
|
@ -2040,11 +2006,11 @@ fn range_search<BorrowType, K, V, Q: ?Sized, R: RangeBounds<Q>>(
|
|||
match (front.force(), back.force()) {
|
||||
(Leaf(f), Leaf(b)) => {
|
||||
return (f, b);
|
||||
},
|
||||
}
|
||||
(Internal(min_int), Internal(max_int)) => {
|
||||
min_node = min_int.descend();
|
||||
max_node = max_int.descend();
|
||||
},
|
||||
}
|
||||
_ => unreachable!("BTreeMap has different depths"),
|
||||
};
|
||||
}
|
||||
|
@ -2321,13 +2287,14 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
|
|||
/// ```
|
||||
#[stable(feature = "entry_and_modify", since = "1.26.0")]
|
||||
pub fn and_modify<F>(self, f: F) -> Self
|
||||
where F: FnOnce(&mut V)
|
||||
where
|
||||
F: FnOnce(&mut V),
|
||||
{
|
||||
match self {
|
||||
Occupied(mut entry) => {
|
||||
f(entry.get_mut());
|
||||
Occupied(entry)
|
||||
},
|
||||
}
|
||||
Vacant(entry) => Vacant(entry),
|
||||
}
|
||||
}
|
||||
|
@ -2354,7 +2321,6 @@ impl<'a, K: Ord, V: Default> Entry<'a, K, V> {
|
|||
Vacant(entry) => entry.insert(Default::default()),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
|
||||
|
@ -2433,17 +2399,15 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
|
|||
|
||||
loop {
|
||||
match cur_parent {
|
||||
Ok(parent) => {
|
||||
match parent.insert(ins_k, ins_v, ins_edge) {
|
||||
Fit(_) => return unsafe { &mut *out_ptr },
|
||||
Split(left, k, v, right) => {
|
||||
ins_k = k;
|
||||
ins_v = v;
|
||||
ins_edge = right;
|
||||
cur_parent = left.ascend().map_err(|n| n.into_root_mut());
|
||||
}
|
||||
Ok(parent) => match parent.insert(ins_k, ins_v, ins_edge) {
|
||||
Fit(_) => return unsafe { &mut *out_ptr },
|
||||
Split(left, k, v, right) => {
|
||||
ins_k = k;
|
||||
ins_v = v;
|
||||
ins_edge = right;
|
||||
cur_parent = left.ascend().map_err(|n| n.into_root_mut());
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(root) => {
|
||||
root.push_level().push(ins_k, ins_v, ins_edge);
|
||||
return unsafe { &mut *out_ptr };
|
||||
|
@ -2669,8 +2633,9 @@ enum UnderflowResult<'a, K, V> {
|
|||
Stole(NodeRef<marker::Mut<'a>, K, V, marker::Internal>),
|
||||
}
|
||||
|
||||
fn handle_underfull_node<K, V>(node: NodeRef<marker::Mut<'_>, K, V, marker::LeafOrInternal>)
|
||||
-> UnderflowResult<'_, K, V> {
|
||||
fn handle_underfull_node<K, V>(
|
||||
node: NodeRef<marker::Mut<'_>, K, V, marker::LeafOrInternal>,
|
||||
) -> UnderflowResult<'_, K, V> {
|
||||
let parent = if let Ok(parent) = node.ascend() {
|
||||
parent
|
||||
} else {
|
||||
|
@ -2679,14 +2644,12 @@ fn handle_underfull_node<K, V>(node: NodeRef<marker::Mut<'_>, K, V, marker::Leaf
|
|||
|
||||
let (is_left, mut handle) = match parent.left_kv() {
|
||||
Ok(left) => (true, left),
|
||||
Err(parent) => {
|
||||
match parent.right_kv() {
|
||||
Ok(right) => (false, right),
|
||||
Err(parent) => {
|
||||
return EmptyParent(parent.into_node());
|
||||
}
|
||||
Err(parent) => match parent.right_kv() {
|
||||
Ok(right) => (false, right),
|
||||
Err(parent) => {
|
||||
return EmptyParent(parent.into_node());
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
if handle.can_merge() {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,14 +2,14 @@
|
|||
// to TreeMap
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::cmp::Ordering::{Less, Greater, Equal};
|
||||
use core::cmp::Ordering::{Equal, Greater, Less};
|
||||
use core::cmp::{max, min};
|
||||
use core::fmt::{self, Debug};
|
||||
use core::iter::{Peekable, FromIterator, FusedIterator};
|
||||
use core::ops::{BitOr, BitAnd, BitXor, Sub, RangeBounds};
|
||||
use core::iter::{FromIterator, FusedIterator, Peekable};
|
||||
use core::ops::{BitAnd, BitOr, BitXor, RangeBounds, Sub};
|
||||
|
||||
use crate::collections::btree_map::{self, BTreeMap, Keys};
|
||||
use super::Recover;
|
||||
use crate::collections::btree_map::{self, BTreeMap, Keys};
|
||||
|
||||
// FIXME(conventions): implement bounded iterators
|
||||
|
||||
|
@ -77,9 +77,7 @@ pub struct Iter<'a, T: 'a> {
|
|||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Iter")
|
||||
.field(&self.iter.clone())
|
||||
.finish()
|
||||
f.debug_tuple("Iter").field(&self.iter.clone()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,8 +112,9 @@ pub struct Range<'a, T: 'a> {
|
|||
/// and crucially for SymmetricDifference, nexts() reports on both sides.
|
||||
#[derive(Clone)]
|
||||
struct MergeIterInner<I>
|
||||
where I: Iterator,
|
||||
I::Item: Copy,
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Copy,
|
||||
{
|
||||
a: I,
|
||||
b: I,
|
||||
|
@ -129,8 +128,9 @@ enum MergeIterPeeked<I: Iterator> {
|
|||
}
|
||||
|
||||
impl<I> MergeIterInner<I>
|
||||
where I: ExactSizeIterator + FusedIterator,
|
||||
I::Item: Copy + Ord,
|
||||
where
|
||||
I: ExactSizeIterator + FusedIterator,
|
||||
I::Item: Copy + Ord,
|
||||
{
|
||||
fn new(a: I, b: I) -> Self {
|
||||
MergeIterInner { a, b, peeked: None }
|
||||
|
@ -169,14 +169,12 @@ impl<I> MergeIterInner<I>
|
|||
}
|
||||
|
||||
impl<I> Debug for MergeIterInner<I>
|
||||
where I: Iterator + Debug,
|
||||
I::Item: Copy + Debug,
|
||||
where
|
||||
I: Iterator + Debug,
|
||||
I::Item: Copy + Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("MergeIterInner")
|
||||
.field(&self.a)
|
||||
.field(&self.b)
|
||||
.finish()
|
||||
f.debug_tuple("MergeIterInner").field(&self.a).field(&self.b).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,7 +326,10 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// ```
|
||||
#[stable(feature = "btree_range", since = "1.17.0")]
|
||||
pub fn range<K: ?Sized, R>(&self, range: R) -> Range<'_, T>
|
||||
where K: Ord, T: Borrow<K>, R: RangeBounds<K>
|
||||
where
|
||||
K: Ord,
|
||||
T: Borrow<K>,
|
||||
R: RangeBounds<K>,
|
||||
{
|
||||
Range { iter: self.map.range(range) }
|
||||
}
|
||||
|
@ -355,24 +356,18 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn difference<'a>(&'a self, other: &'a BTreeSet<T>) -> Difference<'a, T> {
|
||||
let (self_min, self_max) = if let (Some(self_min), Some(self_max)) =
|
||||
(self.first(), self.last())
|
||||
{
|
||||
(self_min, self_max)
|
||||
} else {
|
||||
return Difference {
|
||||
inner: DifferenceInner::Iterate(self.iter()),
|
||||
let (self_min, self_max) =
|
||||
if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) {
|
||||
(self_min, self_max)
|
||||
} else {
|
||||
return Difference { inner: DifferenceInner::Iterate(self.iter()) };
|
||||
};
|
||||
};
|
||||
let (other_min, other_max) = if let (Some(other_min), Some(other_max)) =
|
||||
(other.first(), other.last())
|
||||
{
|
||||
(other_min, other_max)
|
||||
} else {
|
||||
return Difference {
|
||||
inner: DifferenceInner::Iterate(self.iter()),
|
||||
let (other_min, other_max) =
|
||||
if let (Some(other_min), Some(other_max)) = (other.first(), other.last()) {
|
||||
(other_min, other_max)
|
||||
} else {
|
||||
return Difference { inner: DifferenceInner::Iterate(self.iter()) };
|
||||
};
|
||||
};
|
||||
Difference {
|
||||
inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) {
|
||||
(Greater, _) | (_, Less) => DifferenceInner::Iterate(self.iter()),
|
||||
|
@ -387,10 +382,7 @@ impl<T: Ord> BTreeSet<T> {
|
|||
DifferenceInner::Iterate(self_iter)
|
||||
}
|
||||
_ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
|
||||
DifferenceInner::Search {
|
||||
self_iter: self.iter(),
|
||||
other_set: other,
|
||||
}
|
||||
DifferenceInner::Search { self_iter: self.iter(), other_set: other }
|
||||
}
|
||||
_ => DifferenceInner::Stitch {
|
||||
self_iter: self.iter(),
|
||||
|
@ -421,9 +413,10 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// assert_eq!(sym_diff, [1, 3]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn symmetric_difference<'a>(&'a self,
|
||||
other: &'a BTreeSet<T>)
|
||||
-> SymmetricDifference<'a, T> {
|
||||
pub fn symmetric_difference<'a>(
|
||||
&'a self,
|
||||
other: &'a BTreeSet<T>,
|
||||
) -> SymmetricDifference<'a, T> {
|
||||
SymmetricDifference(MergeIterInner::new(self.iter(), other.iter()))
|
||||
}
|
||||
|
||||
|
@ -449,45 +442,30 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn intersection<'a>(&'a self, other: &'a BTreeSet<T>) -> Intersection<'a, T> {
|
||||
let (self_min, self_max) = if let (Some(self_min), Some(self_max)) =
|
||||
(self.first(), self.last())
|
||||
{
|
||||
(self_min, self_max)
|
||||
} else {
|
||||
return Intersection {
|
||||
inner: IntersectionInner::Answer(None),
|
||||
let (self_min, self_max) =
|
||||
if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) {
|
||||
(self_min, self_max)
|
||||
} else {
|
||||
return Intersection { inner: IntersectionInner::Answer(None) };
|
||||
};
|
||||
};
|
||||
let (other_min, other_max) = if let (Some(other_min), Some(other_max)) =
|
||||
(other.first(), other.last())
|
||||
{
|
||||
(other_min, other_max)
|
||||
} else {
|
||||
return Intersection {
|
||||
inner: IntersectionInner::Answer(None),
|
||||
let (other_min, other_max) =
|
||||
if let (Some(other_min), Some(other_max)) = (other.first(), other.last()) {
|
||||
(other_min, other_max)
|
||||
} else {
|
||||
return Intersection { inner: IntersectionInner::Answer(None) };
|
||||
};
|
||||
};
|
||||
Intersection {
|
||||
inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) {
|
||||
(Greater, _) | (_, Less) => IntersectionInner::Answer(None),
|
||||
(Equal, _) => IntersectionInner::Answer(Some(self_min)),
|
||||
(_, Equal) => IntersectionInner::Answer(Some(self_max)),
|
||||
_ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
|
||||
IntersectionInner::Search {
|
||||
small_iter: self.iter(),
|
||||
large_set: other,
|
||||
}
|
||||
IntersectionInner::Search { small_iter: self.iter(), large_set: other }
|
||||
}
|
||||
_ if other.len() <= self.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
|
||||
IntersectionInner::Search {
|
||||
small_iter: other.iter(),
|
||||
large_set: self,
|
||||
}
|
||||
IntersectionInner::Search { small_iter: other.iter(), large_set: self }
|
||||
}
|
||||
_ => IntersectionInner::Stitch {
|
||||
a: self.iter(),
|
||||
b: other.iter(),
|
||||
},
|
||||
_ => IntersectionInner::Stitch { a: self.iter(), b: other.iter() },
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -549,8 +527,9 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
|
||||
where T: Borrow<Q>,
|
||||
Q: Ord
|
||||
where
|
||||
T: Borrow<Q>,
|
||||
Q: Ord,
|
||||
{
|
||||
self.map.contains_key(value)
|
||||
}
|
||||
|
@ -572,8 +551,9 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// ```
|
||||
#[stable(feature = "set_recovery", since = "1.9.0")]
|
||||
pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
|
||||
where T: Borrow<Q>,
|
||||
Q: Ord
|
||||
where
|
||||
T: Borrow<Q>,
|
||||
Q: Ord,
|
||||
{
|
||||
Recover::get(&self.map, value)
|
||||
}
|
||||
|
@ -624,20 +604,18 @@ impl<T: Ord> BTreeSet<T> {
|
|||
if self.len() > other.len() {
|
||||
return false;
|
||||
}
|
||||
let (self_min, self_max) = if let (Some(self_min), Some(self_max)) =
|
||||
(self.first(), self.last())
|
||||
{
|
||||
(self_min, self_max)
|
||||
} else {
|
||||
return true; // self is empty
|
||||
};
|
||||
let (other_min, other_max) = if let (Some(other_min), Some(other_max)) =
|
||||
(other.first(), other.last())
|
||||
{
|
||||
(other_min, other_max)
|
||||
} else {
|
||||
return false; // other is empty
|
||||
};
|
||||
let (self_min, self_max) =
|
||||
if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) {
|
||||
(self_min, self_max)
|
||||
} else {
|
||||
return true; // self is empty
|
||||
};
|
||||
let (other_min, other_max) =
|
||||
if let (Some(other_min), Some(other_max)) = (other.first(), other.last()) {
|
||||
(other_min, other_max)
|
||||
} else {
|
||||
return false; // other is empty
|
||||
};
|
||||
let mut self_iter = self.iter();
|
||||
match self_min.cmp(other_min) {
|
||||
Less => return false,
|
||||
|
@ -855,8 +833,9 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
|
||||
where T: Borrow<Q>,
|
||||
Q: Ord
|
||||
where
|
||||
T: Borrow<Q>,
|
||||
Q: Ord,
|
||||
{
|
||||
self.map.remove(value).is_some()
|
||||
}
|
||||
|
@ -878,8 +857,9 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// ```
|
||||
#[stable(feature = "set_recovery", since = "1.9.0")]
|
||||
pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
|
||||
where T: Borrow<Q>,
|
||||
Q: Ord
|
||||
where
|
||||
T: Borrow<Q>,
|
||||
Q: Ord,
|
||||
{
|
||||
Recover::take(&mut self.map, value)
|
||||
}
|
||||
|
@ -947,7 +927,10 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// assert!(b.contains(&41));
|
||||
/// ```
|
||||
#[stable(feature = "btree_split_off", since = "1.11.0")]
|
||||
pub fn split_off<Q: ?Sized + Ord>(&mut self, key: &Q) -> Self where T: Borrow<Q> {
|
||||
pub fn split_off<Q: ?Sized + Ord>(&mut self, key: &Q) -> Self
|
||||
where
|
||||
T: Borrow<Q>,
|
||||
{
|
||||
BTreeSet { map: self.map.split_off(key) }
|
||||
}
|
||||
}
|
||||
|
@ -1213,7 +1196,9 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
|
|||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> ExactSizeIterator for Iter<'_, T> {
|
||||
fn len(&self) -> usize { self.iter.len() }
|
||||
fn len(&self) -> usize {
|
||||
self.iter.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
|
@ -1238,7 +1223,9 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
|
|||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> ExactSizeIterator for IntoIter<T> {
|
||||
fn len(&self) -> usize { self.iter.len() }
|
||||
fn len(&self) -> usize {
|
||||
self.iter.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
|
@ -1279,20 +1266,13 @@ impl<T> Clone for Difference<'_, T> {
|
|||
fn clone(&self) -> Self {
|
||||
Difference {
|
||||
inner: match &self.inner {
|
||||
DifferenceInner::Stitch {
|
||||
self_iter,
|
||||
other_iter,
|
||||
} => DifferenceInner::Stitch {
|
||||
DifferenceInner::Stitch { self_iter, other_iter } => DifferenceInner::Stitch {
|
||||
self_iter: self_iter.clone(),
|
||||
other_iter: other_iter.clone(),
|
||||
},
|
||||
DifferenceInner::Search {
|
||||
self_iter,
|
||||
other_set,
|
||||
} => DifferenceInner::Search {
|
||||
self_iter: self_iter.clone(),
|
||||
other_set,
|
||||
},
|
||||
DifferenceInner::Search { self_iter, other_set } => {
|
||||
DifferenceInner::Search { self_iter: self_iter.clone(), other_set }
|
||||
}
|
||||
DifferenceInner::Iterate(iter) => DifferenceInner::Iterate(iter.clone()),
|
||||
},
|
||||
}
|
||||
|
@ -1304,16 +1284,10 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> {
|
|||
|
||||
fn next(&mut self) -> Option<&'a T> {
|
||||
match &mut self.inner {
|
||||
DifferenceInner::Stitch {
|
||||
self_iter,
|
||||
other_iter,
|
||||
} => {
|
||||
DifferenceInner::Stitch { self_iter, other_iter } => {
|
||||
let mut self_next = self_iter.next()?;
|
||||
loop {
|
||||
match other_iter
|
||||
.peek()
|
||||
.map_or(Less, |other_next| self_next.cmp(other_next))
|
||||
{
|
||||
match other_iter.peek().map_or(Less, |other_next| self_next.cmp(other_next)) {
|
||||
Less => return Some(self_next),
|
||||
Equal => {
|
||||
self_next = self_iter.next()?;
|
||||
|
@ -1325,10 +1299,7 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
DifferenceInner::Search {
|
||||
self_iter,
|
||||
other_set,
|
||||
} => loop {
|
||||
DifferenceInner::Search { self_iter, other_set } => loop {
|
||||
let self_next = self_iter.next()?;
|
||||
if !other_set.contains(&self_next) {
|
||||
return Some(self_next);
|
||||
|
@ -1340,14 +1311,10 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> {
|
|||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (self_len, other_len) = match &self.inner {
|
||||
DifferenceInner::Stitch {
|
||||
self_iter,
|
||||
other_iter,
|
||||
} => (self_iter.len(), other_iter.len()),
|
||||
DifferenceInner::Search {
|
||||
self_iter,
|
||||
other_set,
|
||||
} => (self_iter.len(), other_set.len()),
|
||||
DifferenceInner::Stitch { self_iter, other_iter } => {
|
||||
(self_iter.len(), other_iter.len())
|
||||
}
|
||||
DifferenceInner::Search { self_iter, other_set } => (self_iter.len(), other_set.len()),
|
||||
DifferenceInner::Iterate(iter) => (iter.len(), 0),
|
||||
};
|
||||
(self_len.saturating_sub(other_len), Some(self_len))
|
||||
|
@ -1393,20 +1360,12 @@ impl<T> Clone for Intersection<'_, T> {
|
|||
fn clone(&self) -> Self {
|
||||
Intersection {
|
||||
inner: match &self.inner {
|
||||
IntersectionInner::Stitch {
|
||||
a,
|
||||
b,
|
||||
} => IntersectionInner::Stitch {
|
||||
a: a.clone(),
|
||||
b: b.clone(),
|
||||
},
|
||||
IntersectionInner::Search {
|
||||
small_iter,
|
||||
large_set,
|
||||
} => IntersectionInner::Search {
|
||||
small_iter: small_iter.clone(),
|
||||
large_set,
|
||||
},
|
||||
IntersectionInner::Stitch { a, b } => {
|
||||
IntersectionInner::Stitch { a: a.clone(), b: b.clone() }
|
||||
}
|
||||
IntersectionInner::Search { small_iter, large_set } => {
|
||||
IntersectionInner::Search { small_iter: small_iter.clone(), large_set }
|
||||
}
|
||||
IntersectionInner::Answer(answer) => IntersectionInner::Answer(*answer),
|
||||
},
|
||||
}
|
||||
|
@ -1418,10 +1377,7 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> {
|
|||
|
||||
fn next(&mut self) -> Option<&'a T> {
|
||||
match &mut self.inner {
|
||||
IntersectionInner::Stitch {
|
||||
a,
|
||||
b,
|
||||
} => {
|
||||
IntersectionInner::Stitch { a, b } => {
|
||||
let mut a_next = a.next()?;
|
||||
let mut b_next = b.next()?;
|
||||
loop {
|
||||
|
@ -1432,10 +1388,7 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
IntersectionInner::Search {
|
||||
small_iter,
|
||||
large_set,
|
||||
} => loop {
|
||||
IntersectionInner::Search { small_iter, large_set } => loop {
|
||||
let small_next = small_iter.next()?;
|
||||
if large_set.contains(&small_next) {
|
||||
return Some(small_next);
|
||||
|
|
|
@ -14,14 +14,14 @@
|
|||
|
||||
use core::cmp::Ordering;
|
||||
use core::fmt;
|
||||
use core::hash::{Hasher, Hash};
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::iter::{FromIterator, FusedIterator};
|
||||
use core::marker::PhantomData;
|
||||
use core::mem;
|
||||
use core::ptr::NonNull;
|
||||
|
||||
use crate::boxed::Box;
|
||||
use super::SpecExtend;
|
||||
use crate::boxed::Box;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -66,9 +66,7 @@ pub struct Iter<'a, T: 'a> {
|
|||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Iter")
|
||||
.field(&self.len)
|
||||
.finish()
|
||||
f.debug_tuple("Iter").field(&self.len).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,10 +99,7 @@ pub struct IterMut<'a, T: 'a> {
|
|||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for IterMut<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("IterMut")
|
||||
.field(&self.list)
|
||||
.field(&self.len)
|
||||
.finish()
|
||||
f.debug_tuple("IterMut").field(&self.list).field(&self.len).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,19 +119,13 @@ pub struct 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.list)
|
||||
.finish()
|
||||
f.debug_tuple("IntoIter").field(&self.list).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Node<T> {
|
||||
fn new(element: T) -> Self {
|
||||
Node {
|
||||
next: None,
|
||||
prev: None,
|
||||
element,
|
||||
}
|
||||
Node { next: None, prev: None, element }
|
||||
}
|
||||
|
||||
fn into_element(self: Box<Self>) -> T {
|
||||
|
@ -278,12 +267,7 @@ impl<T> LinkedList<T> {
|
|||
#[rustc_const_stable(feature = "const_linked_list_new", since = "1.32.0")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const fn new() -> Self {
|
||||
LinkedList {
|
||||
head: None,
|
||||
tail: None,
|
||||
len: 0,
|
||||
marker: PhantomData,
|
||||
}
|
||||
LinkedList { head: None, tail: None, len: 0, marker: PhantomData }
|
||||
}
|
||||
|
||||
/// Moves all elements from `other` to the end of the list.
|
||||
|
@ -357,12 +341,7 @@ impl<T> LinkedList<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn iter(&self) -> Iter<'_, T> {
|
||||
Iter {
|
||||
head: self.head,
|
||||
tail: self.tail,
|
||||
len: self.len,
|
||||
marker: PhantomData,
|
||||
}
|
||||
Iter { head: self.head, tail: self.tail, len: self.len, marker: PhantomData }
|
||||
}
|
||||
|
||||
/// Provides a forward iterator with mutable references.
|
||||
|
@ -391,12 +370,7 @@ impl<T> LinkedList<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
|
||||
IterMut {
|
||||
head: self.head,
|
||||
tail: self.tail,
|
||||
len: self.len,
|
||||
list: self,
|
||||
}
|
||||
IterMut { head: self.head, tail: self.tail, len: self.len, list: self }
|
||||
}
|
||||
|
||||
/// Returns `true` if the `LinkedList` is empty.
|
||||
|
@ -491,7 +465,8 @@ impl<T> LinkedList<T> {
|
|||
/// ```
|
||||
#[stable(feature = "linked_list_contains", since = "1.12.0")]
|
||||
pub fn contains(&self, x: &T) -> bool
|
||||
where T: PartialEq<T>
|
||||
where
|
||||
T: PartialEq<T>,
|
||||
{
|
||||
self.iter().any(|e| e == x)
|
||||
}
|
||||
|
@ -513,9 +488,7 @@ impl<T> LinkedList<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn front(&self) -> Option<&T> {
|
||||
unsafe {
|
||||
self.head.as_ref().map(|node| &node.as_ref().element)
|
||||
}
|
||||
unsafe { self.head.as_ref().map(|node| &node.as_ref().element) }
|
||||
}
|
||||
|
||||
/// Provides a mutable reference to the front element, or `None` if the list
|
||||
|
@ -541,9 +514,7 @@ impl<T> LinkedList<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn front_mut(&mut self) -> Option<&mut T> {
|
||||
unsafe {
|
||||
self.head.as_mut().map(|node| &mut node.as_mut().element)
|
||||
}
|
||||
unsafe { self.head.as_mut().map(|node| &mut node.as_mut().element) }
|
||||
}
|
||||
|
||||
/// Provides a reference to the back element, or `None` if the list is
|
||||
|
@ -563,9 +534,7 @@ impl<T> LinkedList<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn back(&self) -> Option<&T> {
|
||||
unsafe {
|
||||
self.tail.as_ref().map(|node| &node.as_ref().element)
|
||||
}
|
||||
unsafe { self.tail.as_ref().map(|node| &node.as_ref().element) }
|
||||
}
|
||||
|
||||
/// Provides a mutable reference to the back element, or `None` if the list
|
||||
|
@ -591,9 +560,7 @@ impl<T> LinkedList<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn back_mut(&mut self) -> Option<&mut T> {
|
||||
unsafe {
|
||||
self.tail.as_mut().map(|node| &mut node.as_mut().element)
|
||||
}
|
||||
unsafe { self.tail.as_mut().map(|node| &mut node.as_mut().element) }
|
||||
}
|
||||
|
||||
/// Adds an element first in the list.
|
||||
|
@ -790,19 +757,14 @@ impl<T> LinkedList<T> {
|
|||
/// ```
|
||||
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
|
||||
pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F>
|
||||
where F: FnMut(&mut T) -> bool
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
// avoid borrow issues.
|
||||
let it = self.head;
|
||||
let old_len = self.len;
|
||||
|
||||
DrainFilter {
|
||||
list: self,
|
||||
it: it,
|
||||
pred: filter,
|
||||
idx: 0,
|
||||
old_len: old_len,
|
||||
}
|
||||
DrainFilter { list: self, it: it, pred: filter, idx: 0, old_len: old_len }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -960,9 +922,11 @@ impl<T> IterMut<'_, T> {
|
|||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "linked_list_extras",
|
||||
reason = "this is probably better handled by a cursor type -- we'll see",
|
||||
issue = "27794")]
|
||||
#[unstable(
|
||||
feature = "linked_list_extras",
|
||||
reason = "this is probably better handled by a cursor type -- we'll see",
|
||||
issue = "27794"
|
||||
)]
|
||||
pub fn insert_next(&mut self, element: T) {
|
||||
match self.head {
|
||||
// `push_back` is okay with aliasing `element` references
|
||||
|
@ -1008,16 +972,16 @@ impl<T> IterMut<'_, T> {
|
|||
/// assert_eq!(it.next().unwrap(), &2);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "linked_list_extras",
|
||||
reason = "this is probably better handled by a cursor type -- we'll see",
|
||||
issue = "27794")]
|
||||
#[unstable(
|
||||
feature = "linked_list_extras",
|
||||
reason = "this is probably better handled by a cursor type -- we'll see",
|
||||
issue = "27794"
|
||||
)]
|
||||
pub fn peek_next(&mut self) -> Option<&mut T> {
|
||||
if self.len == 0 {
|
||||
None
|
||||
} else {
|
||||
unsafe {
|
||||
self.head.as_mut().map(|node| &mut node.as_mut().element)
|
||||
}
|
||||
unsafe { self.head.as_mut().map(|node| &mut node.as_mut().element) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1025,7 +989,8 @@ impl<T> IterMut<'_, T> {
|
|||
/// An iterator produced by calling `drain_filter` on LinkedList.
|
||||
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
|
||||
pub struct DrainFilter<'a, T: 'a, F: 'a>
|
||||
where F: FnMut(&mut T) -> bool,
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
list: &'a mut LinkedList<T>,
|
||||
it: Option<NonNull<Node<T>>>,
|
||||
|
@ -1036,7 +1001,8 @@ pub struct DrainFilter<'a, T: 'a, F: 'a>
|
|||
|
||||
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
|
||||
impl<T, F> Iterator for DrainFilter<'_, T, F>
|
||||
where F: FnMut(&mut T) -> bool,
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
|
@ -1064,7 +1030,8 @@ impl<T, F> Iterator for DrainFilter<'_, T, F>
|
|||
|
||||
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
|
||||
impl<T, F> Drop for DrainFilter<'_, T, F>
|
||||
where F: FnMut(&mut T) -> bool,
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.for_each(drop);
|
||||
|
@ -1073,12 +1040,11 @@ impl<T, F> Drop for DrainFilter<'_, T, F>
|
|||
|
||||
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
|
||||
impl<T: fmt::Debug, F> fmt::Debug for DrainFilter<'_, T, F>
|
||||
where F: FnMut(&mut T) -> bool
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("DrainFilter")
|
||||
.field(&self.list)
|
||||
.finish()
|
||||
f.debug_tuple("DrainFilter").field(&self.list).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ use crate::alloc::{Layout, LayoutErr};
|
|||
|
||||
/// The error type for `try_reserve` methods.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
|
||||
pub enum TryReserveError {
|
||||
/// Error due to the computed capacity exceeding the collection's maximum
|
||||
/// (usually `isize::MAX` bytes).
|
||||
|
@ -57,15 +57,19 @@ pub enum TryReserveError {
|
|||
layout: Layout,
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "container_error_extra", issue = "none", reason = "\
|
||||
#[unstable(
|
||||
feature = "container_error_extra",
|
||||
issue = "none",
|
||||
reason = "\
|
||||
Enable exposing the allocator’s custom error value \
|
||||
if an associated type is added in the future: \
|
||||
https://github.com/rust-lang/wg-allocators/issues/23")]
|
||||
https://github.com/rust-lang/wg-allocators/issues/23"
|
||||
)]
|
||||
non_exhaustive: (),
|
||||
},
|
||||
}
|
||||
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
|
||||
impl From<LayoutErr> for TryReserveError {
|
||||
#[inline]
|
||||
fn from(_: LayoutErr) -> Self {
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
use core::array::LengthAtMost32;
|
||||
use core::cmp::{self, Ordering};
|
||||
use core::fmt;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::iter::{once, repeat_with, FromIterator, FusedIterator};
|
||||
use core::mem::{self, replace};
|
||||
use core::ops::Bound::{Excluded, Included, Unbounded};
|
||||
use core::ops::{Index, IndexMut, RangeBounds, Try};
|
||||
use core::ptr::{self, NonNull};
|
||||
use core::slice;
|
||||
use core::hash::{Hash, Hasher};
|
||||
|
||||
use crate::collections::TryReserveError;
|
||||
use crate::raw_vec::RawVec;
|
||||
|
@ -89,13 +89,12 @@ impl<'a, 'b, T> PairSlices<'a, 'b, T> {
|
|||
!self.b0.is_empty()
|
||||
}
|
||||
|
||||
fn remainder(self) -> impl Iterator<Item=&'b [T]> {
|
||||
fn remainder(self) -> impl Iterator<Item = &'b [T]> {
|
||||
once(self.b0).chain(once(self.b1))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, T> Iterator for PairSlices<'a, 'b, T>
|
||||
{
|
||||
impl<'a, 'b, T> Iterator for PairSlices<'a, 'b, T> {
|
||||
type Item = (&'a mut [T], &'b [T]);
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
// Get next part length
|
||||
|
@ -247,41 +246,45 @@ impl<T> VecDeque<T> {
|
|||
/// Copies a contiguous block of memory len long from src to dst
|
||||
#[inline]
|
||||
unsafe fn copy(&self, dst: usize, src: usize, len: usize) {
|
||||
debug_assert!(dst + len <= self.cap(),
|
||||
"cpy dst={} src={} len={} cap={}",
|
||||
dst,
|
||||
src,
|
||||
len,
|
||||
self.cap());
|
||||
debug_assert!(src + len <= self.cap(),
|
||||
"cpy dst={} src={} len={} cap={}",
|
||||
dst,
|
||||
src,
|
||||
len,
|
||||
self.cap());
|
||||
ptr::copy(self.ptr().add(src),
|
||||
self.ptr().add(dst),
|
||||
len);
|
||||
debug_assert!(
|
||||
dst + len <= self.cap(),
|
||||
"cpy dst={} src={} len={} cap={}",
|
||||
dst,
|
||||
src,
|
||||
len,
|
||||
self.cap()
|
||||
);
|
||||
debug_assert!(
|
||||
src + len <= self.cap(),
|
||||
"cpy dst={} src={} len={} cap={}",
|
||||
dst,
|
||||
src,
|
||||
len,
|
||||
self.cap()
|
||||
);
|
||||
ptr::copy(self.ptr().add(src), self.ptr().add(dst), len);
|
||||
}
|
||||
|
||||
/// Copies a contiguous block of memory len long from src to dst
|
||||
#[inline]
|
||||
unsafe fn copy_nonoverlapping(&self, dst: usize, src: usize, len: usize) {
|
||||
debug_assert!(dst + len <= self.cap(),
|
||||
"cno dst={} src={} len={} cap={}",
|
||||
dst,
|
||||
src,
|
||||
len,
|
||||
self.cap());
|
||||
debug_assert!(src + len <= self.cap(),
|
||||
"cno dst={} src={} len={} cap={}",
|
||||
dst,
|
||||
src,
|
||||
len,
|
||||
self.cap());
|
||||
ptr::copy_nonoverlapping(self.ptr().add(src),
|
||||
self.ptr().add(dst),
|
||||
len);
|
||||
debug_assert!(
|
||||
dst + len <= self.cap(),
|
||||
"cno dst={} src={} len={} cap={}",
|
||||
dst,
|
||||
src,
|
||||
len,
|
||||
self.cap()
|
||||
);
|
||||
debug_assert!(
|
||||
src + len <= self.cap(),
|
||||
"cno dst={} src={} len={} cap={}",
|
||||
dst,
|
||||
src,
|
||||
len,
|
||||
self.cap()
|
||||
);
|
||||
ptr::copy_nonoverlapping(self.ptr().add(src), self.ptr().add(dst), len);
|
||||
}
|
||||
|
||||
/// Copies a potentially wrapping block of memory len long from src to dest.
|
||||
|
@ -292,12 +295,14 @@ impl<T> VecDeque<T> {
|
|||
fn diff(a: usize, b: usize) -> usize {
|
||||
if a <= b { b - a } else { a - b }
|
||||
}
|
||||
debug_assert!(cmp::min(diff(dst, src), self.cap() - diff(dst, src)) + len <= self.cap(),
|
||||
"wrc dst={} src={} len={} cap={}",
|
||||
dst,
|
||||
src,
|
||||
len,
|
||||
self.cap());
|
||||
debug_assert!(
|
||||
cmp::min(diff(dst, src), self.cap() - diff(dst, src)) + len <= self.cap(),
|
||||
"wrc dst={} src={} len={} cap={}",
|
||||
dst,
|
||||
src,
|
||||
len,
|
||||
self.cap()
|
||||
);
|
||||
|
||||
if src == dst || len == 0 {
|
||||
return;
|
||||
|
@ -475,11 +480,7 @@ impl<T> VecDeque<T> {
|
|||
let cap = cmp::max(capacity + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
|
||||
assert!(cap > capacity, "capacity overflow");
|
||||
|
||||
VecDeque {
|
||||
tail: 0,
|
||||
head: 0,
|
||||
buf: RawVec::with_capacity(cap),
|
||||
}
|
||||
VecDeque { tail: 0, head: 0, buf: RawVec::with_capacity(cap) }
|
||||
}
|
||||
|
||||
/// Retrieves an element in the `VecDeque` by index.
|
||||
|
@ -565,10 +566,7 @@ impl<T> VecDeque<T> {
|
|||
assert!(j < self.len());
|
||||
let ri = self.wrap_add(self.tail, i);
|
||||
let rj = self.wrap_add(self.tail, j);
|
||||
unsafe {
|
||||
ptr::swap(self.ptr().add(ri),
|
||||
self.ptr().add(rj))
|
||||
}
|
||||
unsafe { ptr::swap(self.ptr().add(ri), self.ptr().add(rj)) }
|
||||
}
|
||||
|
||||
/// Returns the number of elements the `VecDeque` can hold without
|
||||
|
@ -635,7 +633,8 @@ impl<T> VecDeque<T> {
|
|||
pub fn reserve(&mut self, additional: usize) {
|
||||
let old_cap = self.cap();
|
||||
let used_cap = self.len() + 1;
|
||||
let new_cap = used_cap.checked_add(additional)
|
||||
let new_cap = used_cap
|
||||
.checked_add(additional)
|
||||
.and_then(|needed_cap| needed_cap.checked_next_power_of_two())
|
||||
.expect("capacity overflow");
|
||||
|
||||
|
@ -683,8 +682,8 @@ impl<T> VecDeque<T> {
|
|||
/// }
|
||||
/// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
|
||||
/// ```
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
|
||||
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
|
||||
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
|
||||
self.try_reserve(additional)
|
||||
}
|
||||
|
||||
|
@ -721,11 +720,12 @@ impl<T> VecDeque<T> {
|
|||
/// }
|
||||
/// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
|
||||
/// ```
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
|
||||
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
|
||||
let old_cap = self.cap();
|
||||
let used_cap = self.len() + 1;
|
||||
let new_cap = used_cap.checked_add(additional)
|
||||
let new_cap = used_cap
|
||||
.checked_add(additional)
|
||||
.and_then(|needed_cap| needed_cap.checked_next_power_of_two())
|
||||
.ok_or(TryReserveError::CapacityOverflow)?;
|
||||
|
||||
|
@ -781,16 +781,14 @@ impl<T> VecDeque<T> {
|
|||
/// buf.shrink_to(0);
|
||||
/// assert!(buf.capacity() >= 4);
|
||||
/// ```
|
||||
#[unstable(feature = "shrink_to", reason = "new API", issue="56431")]
|
||||
#[unstable(feature = "shrink_to", reason = "new API", issue = "56431")]
|
||||
pub fn shrink_to(&mut self, min_capacity: usize) {
|
||||
assert!(self.capacity() >= min_capacity, "Tried to shrink to a larger capacity");
|
||||
|
||||
// +1 since the ringbuffer always leaves one space empty
|
||||
// len + 1 can't overflow for an existing, well-formed ringbuffer.
|
||||
let target_cap = cmp::max(
|
||||
cmp::max(min_capacity, self.len()) + 1,
|
||||
MINIMUM_CAPACITY + 1
|
||||
).next_power_of_two();
|
||||
let target_cap = cmp::max(cmp::max(min_capacity, self.len()) + 1, MINIMUM_CAPACITY + 1)
|
||||
.next_power_of_two();
|
||||
|
||||
if target_cap < self.cap() {
|
||||
// There are three cases of interest:
|
||||
|
@ -913,11 +911,7 @@ impl<T> VecDeque<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn iter(&self) -> Iter<'_, T> {
|
||||
Iter {
|
||||
tail: self.tail,
|
||||
head: self.head,
|
||||
ring: unsafe { self.buffer_as_slice() },
|
||||
}
|
||||
Iter { tail: self.tail, head: self.head, ring: unsafe { self.buffer_as_slice() } }
|
||||
}
|
||||
|
||||
/// Returns a front-to-back iterator that returns mutable references.
|
||||
|
@ -939,11 +933,7 @@ impl<T> VecDeque<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
|
||||
IterMut {
|
||||
tail: self.tail,
|
||||
head: self.head,
|
||||
ring: unsafe { self.buffer_as_mut_slice() },
|
||||
}
|
||||
IterMut { tail: self.tail, head: self.head, ring: unsafe { self.buffer_as_mut_slice() } }
|
||||
}
|
||||
|
||||
/// Returns a pair of slices which contain, in order, the contents of the
|
||||
|
@ -1073,7 +1063,8 @@ impl<T> VecDeque<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
|
||||
where R: RangeBounds<usize>
|
||||
where
|
||||
R: RangeBounds<usize>,
|
||||
{
|
||||
// Memory safety
|
||||
//
|
||||
|
@ -1089,12 +1080,12 @@ impl<T> VecDeque<T> {
|
|||
let start = match range.start_bound() {
|
||||
Included(&n) => n,
|
||||
Excluded(&n) => n + 1,
|
||||
Unbounded => 0,
|
||||
Unbounded => 0,
|
||||
};
|
||||
let end = match range.end_bound() {
|
||||
Included(&n) => n + 1,
|
||||
Excluded(&n) => n,
|
||||
Unbounded => len,
|
||||
Unbounded => len,
|
||||
};
|
||||
assert!(start <= end, "drain lower bound was too large");
|
||||
assert!(end <= len, "drain upper bound was too large");
|
||||
|
@ -1174,7 +1165,8 @@ impl<T> VecDeque<T> {
|
|||
/// ```
|
||||
#[stable(feature = "vec_deque_contains", since = "1.12.0")]
|
||||
pub fn contains(&self, x: &T) -> bool
|
||||
where T: PartialEq<T>
|
||||
where
|
||||
T: PartialEq<T>,
|
||||
{
|
||||
let (a, b) = self.as_slices();
|
||||
a.contains(x) || b.contains(x)
|
||||
|
@ -1197,11 +1189,7 @@ impl<T> VecDeque<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn front(&self) -> Option<&T> {
|
||||
if !self.is_empty() {
|
||||
Some(&self[0])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if !self.is_empty() { Some(&self[0]) } else { None }
|
||||
}
|
||||
|
||||
/// Provides a mutable reference to the front element, or `None` if the
|
||||
|
@ -1225,11 +1213,7 @@ impl<T> VecDeque<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn front_mut(&mut self) -> Option<&mut T> {
|
||||
if !self.is_empty() {
|
||||
Some(&mut self[0])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if !self.is_empty() { Some(&mut self[0]) } else { None }
|
||||
}
|
||||
|
||||
/// Provides a reference to the back element, or `None` if the `VecDeque` is
|
||||
|
@ -1249,11 +1233,7 @@ impl<T> VecDeque<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn back(&self) -> Option<&T> {
|
||||
if !self.is_empty() {
|
||||
Some(&self[self.len() - 1])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if !self.is_empty() { Some(&self[self.len() - 1]) } else { None }
|
||||
}
|
||||
|
||||
/// Provides a mutable reference to the back element, or `None` if the
|
||||
|
@ -1278,11 +1258,7 @@ impl<T> VecDeque<T> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn back_mut(&mut self) -> Option<&mut T> {
|
||||
let len = self.len();
|
||||
if !self.is_empty() {
|
||||
Some(&mut self[len - 1])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if !self.is_empty() { Some(&mut self[len - 1]) } else { None }
|
||||
}
|
||||
|
||||
/// Removes the first element and returns it, or `None` if the `VecDeque` is
|
||||
|
@ -1897,22 +1873,24 @@ impl<T> VecDeque<T> {
|
|||
// `at` lies in the first half.
|
||||
let amount_in_first = first_len - at;
|
||||
|
||||
ptr::copy_nonoverlapping(first_half.as_ptr().add(at),
|
||||
other.ptr(),
|
||||
amount_in_first);
|
||||
ptr::copy_nonoverlapping(first_half.as_ptr().add(at), other.ptr(), amount_in_first);
|
||||
|
||||
// just take all of the second half.
|
||||
ptr::copy_nonoverlapping(second_half.as_ptr(),
|
||||
other.ptr().add(amount_in_first),
|
||||
second_len);
|
||||
ptr::copy_nonoverlapping(
|
||||
second_half.as_ptr(),
|
||||
other.ptr().add(amount_in_first),
|
||||
second_len,
|
||||
);
|
||||
} else {
|
||||
// `at` lies in the second half, need to factor in the elements we skipped
|
||||
// in the first half.
|
||||
let offset = at - first_len;
|
||||
let amount_in_second = second_len - offset;
|
||||
ptr::copy_nonoverlapping(second_half.as_ptr().add(offset),
|
||||
other.ptr(),
|
||||
amount_in_second);
|
||||
ptr::copy_nonoverlapping(
|
||||
second_half.as_ptr().add(offset),
|
||||
other.ptr(),
|
||||
amount_in_second,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1979,7 +1957,8 @@ impl<T> VecDeque<T> {
|
|||
/// ```
|
||||
#[stable(feature = "vec_deque_retain", since = "1.4.0")]
|
||||
pub fn retain<F>(&mut self, mut f: F)
|
||||
where F: FnMut(&T) -> bool
|
||||
where
|
||||
F: FnMut(&T) -> bool,
|
||||
{
|
||||
let len = self.len();
|
||||
let mut del = 0;
|
||||
|
@ -2034,7 +2013,7 @@ impl<T> VecDeque<T> {
|
|||
/// assert_eq!(buf, [5, 10, 101, 102, 103]);
|
||||
/// ```
|
||||
#[stable(feature = "vec_resize_with", since = "1.33.0")]
|
||||
pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut()->T) {
|
||||
pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut() -> T) {
|
||||
let len = self.len();
|
||||
|
||||
if new_len > len {
|
||||
|
@ -2250,10 +2229,7 @@ pub struct Iter<'a, T: 'a> {
|
|||
impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
|
||||
f.debug_tuple("Iter")
|
||||
.field(&front)
|
||||
.field(&back)
|
||||
.finish()
|
||||
f.debug_tuple("Iter").field(&front).field(&back).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2261,11 +2237,7 @@ impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Clone for Iter<'_, T> {
|
||||
fn clone(&self) -> Self {
|
||||
Iter {
|
||||
ring: self.ring,
|
||||
tail: self.tail,
|
||||
head: self.head,
|
||||
}
|
||||
Iter { ring: self.ring, tail: self.tail, head: self.head }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2290,7 +2262,8 @@ impl<'a, T> Iterator for Iter<'a, T> {
|
|||
}
|
||||
|
||||
fn fold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
|
||||
where F: FnMut(Acc, Self::Item) -> Acc
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
|
||||
accum = front.iter().fold(accum, &mut f);
|
||||
|
@ -2350,7 +2323,8 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
|
|||
}
|
||||
|
||||
fn rfold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
|
||||
where F: FnMut(Acc, Self::Item) -> Acc
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
|
||||
accum = back.iter().rfold(accum, &mut f);
|
||||
|
@ -2392,7 +2366,6 @@ impl<T> ExactSizeIterator for Iter<'_, T> {
|
|||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<T> FusedIterator for Iter<'_, T> {}
|
||||
|
||||
|
||||
/// A mutable iterator over the elements of a `VecDeque`.
|
||||
///
|
||||
/// This `struct` is created by the [`iter_mut`] method on [`VecDeque`]. See its
|
||||
|
@ -2411,10 +2384,7 @@ pub struct IterMut<'a, T: 'a> {
|
|||
impl<T: fmt::Debug> fmt::Debug for IterMut<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let (front, back) = RingSlices::ring_slices(&*self.ring, self.head, self.tail);
|
||||
f.debug_tuple("IterMut")
|
||||
.field(&front)
|
||||
.field(&back)
|
||||
.finish()
|
||||
f.debug_tuple("IterMut").field(&front).field(&back).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2443,7 +2413,8 @@ impl<'a, T> Iterator for IterMut<'a, T> {
|
|||
}
|
||||
|
||||
fn fold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
|
||||
where F: FnMut(Acc, Self::Item) -> Acc
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
|
||||
accum = front.iter_mut().fold(accum, &mut f);
|
||||
|
@ -2482,7 +2453,8 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
|
|||
}
|
||||
|
||||
fn rfold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
|
||||
where F: FnMut(Acc, Self::Item) -> Acc
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
|
||||
accum = back.iter_mut().rfold(accum, &mut f);
|
||||
|
@ -2516,9 +2488,7 @@ pub struct 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.inner)
|
||||
.finish()
|
||||
f.debug_tuple("IntoIter").field(&self.inner).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2575,10 +2545,10 @@ pub struct Drain<'a, T: 'a> {
|
|||
impl<T: fmt::Debug> fmt::Debug for Drain<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Drain")
|
||||
.field(&self.after_tail)
|
||||
.field(&self.after_head)
|
||||
.field(&self.iter)
|
||||
.finish()
|
||||
.field(&self.after_tail)
|
||||
.field(&self.after_head)
|
||||
.field(&self.iter)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2835,7 +2805,9 @@ impl<A> Extend<A> for VecDeque<A> {
|
|||
|
||||
let head = self.head;
|
||||
self.head = self.wrap_add(self.head, 1);
|
||||
unsafe { self.buffer_write(head, element); }
|
||||
unsafe {
|
||||
self.buffer_write(head, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2873,17 +2845,15 @@ impl<T> From<Vec<T>> for VecDeque<T> {
|
|||
|
||||
// We need to extend the buf if it's not a power of two, too small
|
||||
// or doesn't have at least one free space
|
||||
if !buf.capacity().is_power_of_two() || (buf.capacity() < (MINIMUM_CAPACITY + 1)) ||
|
||||
(buf.capacity() == len) {
|
||||
if !buf.capacity().is_power_of_two()
|
||||
|| (buf.capacity() < (MINIMUM_CAPACITY + 1))
|
||||
|| (buf.capacity() == len)
|
||||
{
|
||||
let cap = cmp::max(buf.capacity() + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
|
||||
buf.reserve_exact(len, cap - len);
|
||||
}
|
||||
|
||||
VecDeque {
|
||||
tail: 0,
|
||||
head: len,
|
||||
buf,
|
||||
}
|
||||
VecDeque { tail: 0, head: len, buf }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2936,9 +2906,7 @@ impl<T> From<VecDeque<T>> for Vec<T> {
|
|||
// do this in at most three copy moves.
|
||||
if (cap - tail) > head {
|
||||
// right hand block is the long one; move that enough for the left
|
||||
ptr::copy(buf.add(tail),
|
||||
buf.add(tail - head),
|
||||
cap - tail);
|
||||
ptr::copy(buf.add(tail), buf.add(tail - head), cap - tail);
|
||||
// copy left in the end
|
||||
ptr::copy(buf, buf.add(cap - head), head);
|
||||
// shift the new thing to the start
|
||||
|
@ -2976,10 +2944,8 @@ impl<T> From<VecDeque<T>> for Vec<T> {
|
|||
let n_ops = right_edge - left_edge;
|
||||
left_edge += n_ops;
|
||||
right_edge += right_offset + 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
let out = Vec::from_raw_parts(buf, len, cap);
|
||||
mem::forget(other);
|
||||
|
|
|
@ -58,22 +58,21 @@
|
|||
|
||||
#![allow(unused_attributes)]
|
||||
#![stable(feature = "alloc", since = "1.36.0")]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
|
||||
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
|
||||
test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
|
||||
#![doc(
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/",
|
||||
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
|
||||
test(no_crate_inject, attr(allow(unused_variables), deny(warnings)))
|
||||
)]
|
||||
#![no_std]
|
||||
#![needs_allocator]
|
||||
|
||||
#![warn(deprecated_in_future)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(missing_debug_implementations)]
|
||||
#![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings
|
||||
#![allow(explicit_outlives_requirements)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
#![cfg_attr(not(test), feature(generator_trait))]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
|
||||
#![feature(allocator_api)]
|
||||
#![feature(allow_internal_unstable)]
|
||||
#![feature(arbitrary_self_types)]
|
||||
|
@ -150,19 +149,19 @@ pub mod boxed;
|
|||
mod boxed {
|
||||
pub use std::boxed::Box;
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
pub mod collections;
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
pub mod sync;
|
||||
pub mod rc;
|
||||
pub mod raw_vec;
|
||||
pub mod prelude;
|
||||
pub mod borrow;
|
||||
pub mod collections;
|
||||
pub mod fmt;
|
||||
pub mod prelude;
|
||||
pub mod raw_vec;
|
||||
pub mod rc;
|
||||
pub mod slice;
|
||||
pub mod str;
|
||||
pub mod string;
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
pub mod sync;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
pub mod vec;
|
||||
|
||||
#[cfg(not(test))]
|
||||
|
|
|
@ -7,9 +7,9 @@ use core::ops::Drop;
|
|||
use core::ptr::{self, NonNull, Unique};
|
||||
use core::slice;
|
||||
|
||||
use crate::alloc::{Alloc, Layout, Global, AllocErr, handle_alloc_error};
|
||||
use crate::collections::TryReserveError::{self, *};
|
||||
use crate::alloc::{handle_alloc_error, Alloc, AllocErr, Global, Layout};
|
||||
use crate::boxed::Box;
|
||||
use crate::collections::TryReserveError::{self, *};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -55,11 +55,7 @@ impl<T, A: Alloc> RawVec<T, A> {
|
|||
let cap = if mem::size_of::<T>() == 0 { core::usize::MAX } else { 0 };
|
||||
|
||||
// `Unique::empty()` doubles as "unallocated" and "zero-sized allocation".
|
||||
RawVec {
|
||||
ptr: Unique::empty(),
|
||||
cap,
|
||||
a,
|
||||
}
|
||||
RawVec { ptr: Unique::empty(), cap, a }
|
||||
}
|
||||
|
||||
/// Like `with_capacity`, but parameterized over the choice of
|
||||
|
@ -89,22 +85,14 @@ impl<T, A: Alloc> RawVec<T, A> {
|
|||
} else {
|
||||
let align = mem::align_of::<T>();
|
||||
let layout = Layout::from_size_align(alloc_size, align).unwrap();
|
||||
let result = if zeroed {
|
||||
a.alloc_zeroed(layout)
|
||||
} else {
|
||||
a.alloc(layout)
|
||||
};
|
||||
let result = if zeroed { a.alloc_zeroed(layout) } else { a.alloc(layout) };
|
||||
match result {
|
||||
Ok(ptr) => ptr.cast(),
|
||||
Err(_) => handle_alloc_error(layout),
|
||||
}
|
||||
};
|
||||
|
||||
RawVec {
|
||||
ptr: ptr.into(),
|
||||
cap: capacity,
|
||||
a,
|
||||
}
|
||||
RawVec { ptr: ptr.into(), cap: capacity, a }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -168,11 +156,7 @@ impl<T, A: Alloc> RawVec<T, A> {
|
|||
/// The `capacity` cannot exceed `isize::MAX` (only a concern on 32-bit systems).
|
||||
/// If the `ptr` and `capacity` come from a `RawVec` created via `a`, then this is guaranteed.
|
||||
pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, a: A) -> Self {
|
||||
RawVec {
|
||||
ptr: Unique::new_unchecked(ptr),
|
||||
cap: capacity,
|
||||
a,
|
||||
}
|
||||
RawVec { ptr: Unique::new_unchecked(ptr), cap: capacity, a }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,11 +169,7 @@ impl<T> RawVec<T, Global> {
|
|||
/// The `capacity` cannot exceed `isize::MAX` (only a concern on 32-bit systems).
|
||||
/// If the `ptr` and `capacity` come from a `RawVec`, then this is guaranteed.
|
||||
pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self {
|
||||
RawVec {
|
||||
ptr: Unique::new_unchecked(ptr),
|
||||
cap: capacity,
|
||||
a: Global,
|
||||
}
|
||||
RawVec { ptr: Unique::new_unchecked(ptr), cap: capacity, a: Global }
|
||||
}
|
||||
|
||||
/// Converts a `Box<[T]>` into a `RawVec<T>`.
|
||||
|
@ -215,11 +195,7 @@ impl<T, A: Alloc> RawVec<T, A> {
|
|||
/// This will always be `usize::MAX` if `T` is zero-sized.
|
||||
#[inline(always)]
|
||||
pub fn capacity(&self) -> usize {
|
||||
if mem::size_of::<T>() == 0 {
|
||||
!0
|
||||
} else {
|
||||
self.cap
|
||||
}
|
||||
if mem::size_of::<T>() == 0 { !0 } else { self.cap }
|
||||
}
|
||||
|
||||
/// Returns a shared reference to the allocator backing this `RawVec`.
|
||||
|
@ -319,14 +295,13 @@ impl<T, A: Alloc> RawVec<T, A> {
|
|||
let new_cap = 2 * self.cap;
|
||||
let new_size = new_cap * elem_size;
|
||||
alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow());
|
||||
let ptr_res = self.a.realloc(NonNull::from(self.ptr).cast(),
|
||||
cur,
|
||||
new_size);
|
||||
let ptr_res = self.a.realloc(NonNull::from(self.ptr).cast(), cur, new_size);
|
||||
match ptr_res {
|
||||
Ok(ptr) => (new_cap, ptr.cast().into()),
|
||||
Err(_) => handle_alloc_error(
|
||||
Layout::from_size_align_unchecked(new_size, cur.align())
|
||||
),
|
||||
Err(_) => handle_alloc_error(Layout::from_size_align_unchecked(
|
||||
new_size,
|
||||
cur.align(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
None => {
|
||||
|
@ -386,17 +361,17 @@ impl<T, A: Alloc> RawVec<T, A> {
|
|||
self.cap = new_cap;
|
||||
true
|
||||
}
|
||||
Err(_) => {
|
||||
false
|
||||
}
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The same as `reserve_exact`, but returns on errors instead of panicking or aborting.
|
||||
pub fn try_reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize)
|
||||
-> Result<(), TryReserveError> {
|
||||
|
||||
pub fn try_reserve_exact(
|
||||
&mut self,
|
||||
used_capacity: usize,
|
||||
needed_extra_capacity: usize,
|
||||
) -> Result<(), TryReserveError> {
|
||||
self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Exact)
|
||||
}
|
||||
|
||||
|
@ -425,18 +400,20 @@ impl<T, A: Alloc> RawVec<T, A> {
|
|||
Err(CapacityOverflow) => capacity_overflow(),
|
||||
Err(AllocError { .. }) => unreachable!(),
|
||||
Ok(()) => { /* yay */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates the buffer's new size given that it'll hold `used_capacity +
|
||||
/// needed_extra_capacity` elements. This logic is used in amortized reserve methods.
|
||||
/// Returns `(new_capacity, new_alloc_size)`.
|
||||
fn amortized_new_size(&self, used_capacity: usize, needed_extra_capacity: usize)
|
||||
-> Result<usize, TryReserveError> {
|
||||
|
||||
fn amortized_new_size(
|
||||
&self,
|
||||
used_capacity: usize,
|
||||
needed_extra_capacity: usize,
|
||||
) -> Result<usize, TryReserveError> {
|
||||
// Nothing we can really do about these checks, sadly.
|
||||
let required_cap = used_capacity.checked_add(needed_extra_capacity)
|
||||
.ok_or(CapacityOverflow)?;
|
||||
let required_cap =
|
||||
used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?;
|
||||
// Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`.
|
||||
let double_cap = self.cap * 2;
|
||||
// `double_cap` guarantees exponential growth.
|
||||
|
@ -444,8 +421,11 @@ impl<T, A: Alloc> RawVec<T, A> {
|
|||
}
|
||||
|
||||
/// The same as `reserve`, but returns on errors instead of panicking or aborting.
|
||||
pub fn try_reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize)
|
||||
-> Result<(), TryReserveError> {
|
||||
pub fn try_reserve(
|
||||
&mut self,
|
||||
used_capacity: usize,
|
||||
needed_extra_capacity: usize,
|
||||
) -> Result<(), TryReserveError> {
|
||||
self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Amortized)
|
||||
}
|
||||
|
||||
|
@ -543,7 +523,8 @@ impl<T, A: Alloc> RawVec<T, A> {
|
|||
return false;
|
||||
}
|
||||
|
||||
let new_cap = self.amortized_new_size(used_capacity, needed_extra_capacity)
|
||||
let new_cap = self
|
||||
.amortized_new_size(used_capacity, needed_extra_capacity)
|
||||
.unwrap_or_else(|_| capacity_overflow());
|
||||
|
||||
// Here, `cap < used_capacity + needed_extra_capacity <= new_cap`
|
||||
|
@ -554,15 +535,15 @@ impl<T, A: Alloc> RawVec<T, A> {
|
|||
// FIXME: may crash and burn on over-reserve
|
||||
alloc_guard(new_layout.size()).unwrap_or_else(|_| capacity_overflow());
|
||||
match self.a.grow_in_place(
|
||||
NonNull::from(self.ptr).cast(), old_layout, new_layout.size(),
|
||||
NonNull::from(self.ptr).cast(),
|
||||
old_layout,
|
||||
new_layout.size(),
|
||||
) {
|
||||
Ok(_) => {
|
||||
self.cap = new_cap;
|
||||
true
|
||||
}
|
||||
Err(_) => {
|
||||
false
|
||||
}
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -615,13 +596,11 @@ impl<T, A: Alloc> RawVec<T, A> {
|
|||
let new_size = elem_size * amount;
|
||||
let align = mem::align_of::<T>();
|
||||
let old_layout = Layout::from_size_align_unchecked(old_size, align);
|
||||
match self.a.realloc(NonNull::from(self.ptr).cast(),
|
||||
old_layout,
|
||||
new_size) {
|
||||
match self.a.realloc(NonNull::from(self.ptr).cast(), old_layout, new_size) {
|
||||
Ok(p) => self.ptr = p.cast().into(),
|
||||
Err(_) => handle_alloc_error(
|
||||
Layout::from_size_align_unchecked(new_size, align)
|
||||
),
|
||||
Err(_) => {
|
||||
handle_alloc_error(Layout::from_size_align_unchecked(new_size, align))
|
||||
}
|
||||
}
|
||||
}
|
||||
self.cap = amount;
|
||||
|
@ -665,7 +644,9 @@ impl<T, A: Alloc> RawVec<T, A> {
|
|||
|
||||
// Nothing we can really do about these checks, sadly.
|
||||
let new_cap = match strategy {
|
||||
Exact => used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?,
|
||||
Exact => {
|
||||
used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?
|
||||
}
|
||||
Amortized => self.amortized_new_size(used_capacity, needed_extra_capacity)?,
|
||||
};
|
||||
let new_layout = Layout::array::<T>(new_cap).map_err(|_| CapacityOverflow)?;
|
||||
|
@ -682,10 +663,12 @@ impl<T, A: Alloc> RawVec<T, A> {
|
|||
|
||||
let ptr = match (res, fallibility) {
|
||||
(Err(AllocErr), Infallible) => handle_alloc_error(new_layout),
|
||||
(Err(AllocErr), Fallible) => return Err(TryReserveError::AllocError {
|
||||
layout: new_layout,
|
||||
non_exhaustive: (),
|
||||
}),
|
||||
(Err(AllocErr), Fallible) => {
|
||||
return Err(TryReserveError::AllocError {
|
||||
layout: new_layout,
|
||||
non_exhaustive: (),
|
||||
});
|
||||
}
|
||||
(Ok(ptr), _) => ptr,
|
||||
};
|
||||
|
||||
|
@ -695,7 +678,6 @@ impl<T, A: Alloc> RawVec<T, A> {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<T> RawVec<T, Global> {
|
||||
|
@ -733,7 +715,9 @@ impl<T, A: Alloc> RawVec<T, A> {
|
|||
unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec<T, A> {
|
||||
/// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.dealloc_buffer(); }
|
||||
unsafe {
|
||||
self.dealloc_buffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -239,20 +239,20 @@ use core::array::LengthAtMost32;
|
|||
use core::borrow;
|
||||
use core::cell::Cell;
|
||||
use core::cmp::Ordering;
|
||||
use core::convert::{From, TryFrom};
|
||||
use core::fmt;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::intrinsics::abort;
|
||||
use core::iter;
|
||||
use core::marker::{self, Unpin, Unsize, PhantomData};
|
||||
use core::marker::{self, PhantomData, Unpin, Unsize};
|
||||
use core::mem::{self, align_of, align_of_val, forget, size_of_val};
|
||||
use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn};
|
||||
use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver};
|
||||
use core::pin::Pin;
|
||||
use core::ptr::{self, NonNull};
|
||||
use core::slice::{self, from_raw_parts_mut};
|
||||
use core::convert::{From, TryFrom};
|
||||
use core::usize;
|
||||
|
||||
use crate::alloc::{Global, Alloc, Layout, box_free, handle_alloc_error};
|
||||
use crate::alloc::{box_free, handle_alloc_error, Alloc, Global, Layout};
|
||||
use crate::string::String;
|
||||
use crate::vec::Vec;
|
||||
|
||||
|
@ -296,10 +296,7 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T> {}
|
|||
|
||||
impl<T: ?Sized> Rc<T> {
|
||||
fn from_inner(ptr: NonNull<RcBox<T>>) -> Self {
|
||||
Self {
|
||||
ptr,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
Self { ptr, phantom: PhantomData }
|
||||
}
|
||||
|
||||
unsafe fn from_ptr(ptr: *mut RcBox<T>) -> Self {
|
||||
|
@ -354,10 +351,9 @@ impl<T> Rc<T> {
|
|||
#[unstable(feature = "new_uninit", issue = "63291")]
|
||||
pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> {
|
||||
unsafe {
|
||||
Rc::from_ptr(Rc::allocate_for_layout(
|
||||
Layout::new::<T>(),
|
||||
|mem| mem as *mut RcBox<mem::MaybeUninit<T>>,
|
||||
))
|
||||
Rc::from_ptr(Rc::allocate_for_layout(Layout::new::<T>(), |mem| {
|
||||
mem as *mut RcBox<mem::MaybeUninit<T>>
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,9 +462,7 @@ impl<T> Rc<[T]> {
|
|||
/// ```
|
||||
#[unstable(feature = "new_uninit", issue = "63291")]
|
||||
pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> {
|
||||
unsafe {
|
||||
Rc::from_ptr(Rc::allocate_for_slice(len))
|
||||
}
|
||||
unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -733,13 +727,7 @@ impl<T: ?Sized> Rc<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "rc_unique", since = "1.4.0")]
|
||||
pub fn get_mut(this: &mut Self) -> Option<&mut T> {
|
||||
if Rc::is_unique(this) {
|
||||
unsafe {
|
||||
Some(Rc::get_mut_unchecked(this))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if Rc::is_unique(this) { unsafe { Some(Rc::get_mut_unchecked(this)) } } else { None }
|
||||
}
|
||||
|
||||
/// Returns a mutable reference into the given `Rc`,
|
||||
|
@ -872,9 +860,7 @@ impl<T: Clone> Rc<T> {
|
|||
// reference count is guaranteed to be 1 at this point, and we required
|
||||
// the `Rc<T>` itself to be `mut`, so we're returning the only possible
|
||||
// reference to the allocation.
|
||||
unsafe {
|
||||
&mut this.ptr.as_mut().value
|
||||
}
|
||||
unsafe { &mut this.ptr.as_mut().value }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -918,19 +904,16 @@ impl<T: ?Sized> Rc<T> {
|
|||
/// and must return back a (potentially fat)-pointer for the `RcBox<T>`.
|
||||
unsafe fn allocate_for_layout(
|
||||
value_layout: Layout,
|
||||
mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox<T>
|
||||
mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox<T>,
|
||||
) -> *mut RcBox<T> {
|
||||
// Calculate layout using the given value layout.
|
||||
// Previously, layout was calculated on the expression
|
||||
// `&*(ptr as *const RcBox<T>)`, but this created a misaligned
|
||||
// reference (see #54908).
|
||||
let layout = Layout::new::<RcBox<()>>()
|
||||
.extend(value_layout).unwrap().0
|
||||
.pad_to_align();
|
||||
let layout = Layout::new::<RcBox<()>>().extend(value_layout).unwrap().0.pad_to_align();
|
||||
|
||||
// Allocate for the layout.
|
||||
let mem = Global.alloc(layout)
|
||||
.unwrap_or_else(|_| handle_alloc_error(layout));
|
||||
let mem = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
|
||||
|
||||
// Initialize the RcBox
|
||||
let inner = mem_to_rcbox(mem.as_ptr());
|
||||
|
@ -945,10 +928,9 @@ impl<T: ?Sized> Rc<T> {
|
|||
/// Allocates an `RcBox<T>` with sufficient space for an unsized inner value
|
||||
unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
|
||||
// Allocate for the `RcBox<T>` using the given value.
|
||||
Self::allocate_for_layout(
|
||||
Layout::for_value(&*ptr),
|
||||
|mem| set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>,
|
||||
)
|
||||
Self::allocate_for_layout(Layout::for_value(&*ptr), |mem| {
|
||||
set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>
|
||||
})
|
||||
}
|
||||
|
||||
fn from_box(v: Box<T>) -> Rc<T> {
|
||||
|
@ -963,7 +945,8 @@ impl<T: ?Sized> Rc<T> {
|
|||
ptr::copy_nonoverlapping(
|
||||
bptr as *const T as *const u8,
|
||||
&mut (*ptr).value as *mut _ as *mut u8,
|
||||
value_size);
|
||||
value_size,
|
||||
);
|
||||
|
||||
// Free the allocation without dropping its contents
|
||||
box_free(box_unique);
|
||||
|
@ -976,10 +959,9 @@ impl<T: ?Sized> Rc<T> {
|
|||
impl<T> Rc<[T]> {
|
||||
/// Allocates an `RcBox<[T]>` with the given length.
|
||||
unsafe fn allocate_for_slice(len: usize) -> *mut RcBox<[T]> {
|
||||
Self::allocate_for_layout(
|
||||
Layout::array::<T>(len).unwrap(),
|
||||
|mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut RcBox<[T]>,
|
||||
)
|
||||
Self::allocate_for_layout(Layout::array::<T>(len).unwrap(), |mem| {
|
||||
ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut RcBox<[T]>
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -999,10 +981,7 @@ impl<T> Rc<[T]> {
|
|||
unsafe fn copy_from_slice(v: &[T]) -> Rc<[T]> {
|
||||
let ptr = Self::allocate_for_slice(v.len());
|
||||
|
||||
ptr::copy_nonoverlapping(
|
||||
v.as_ptr(),
|
||||
&mut (*ptr).value as *mut [T] as *mut T,
|
||||
v.len());
|
||||
ptr::copy_nonoverlapping(v.as_ptr(), &mut (*ptr).value as *mut [T] as *mut T, v.len());
|
||||
|
||||
Self::from_ptr(ptr)
|
||||
}
|
||||
|
@ -1040,12 +1019,7 @@ impl<T> Rc<[T]> {
|
|||
// Pointer to first element
|
||||
let elems = &mut (*ptr).value as *mut [T] as *mut T;
|
||||
|
||||
let mut guard = Guard {
|
||||
mem: NonNull::new_unchecked(mem),
|
||||
elems,
|
||||
layout,
|
||||
n_elems: 0,
|
||||
};
|
||||
let mut guard = Guard { mem: NonNull::new_unchecked(mem), elems, layout, n_elems: 0 };
|
||||
|
||||
for (i, item) in iter.enumerate() {
|
||||
ptr::write(elems.add(i), item);
|
||||
|
@ -1067,9 +1041,7 @@ trait RcFromSlice<T> {
|
|||
impl<T: Clone> RcFromSlice<T> for Rc<[T]> {
|
||||
#[inline]
|
||||
default fn from_slice(v: &[T]) -> Self {
|
||||
unsafe {
|
||||
Self::from_iter_exact(v.iter().cloned(), v.len())
|
||||
}
|
||||
unsafe { Self::from_iter_exact(v.iter().cloned(), v.len()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1543,13 +1515,14 @@ impl<T, I: Iterator<Item = T>> RcFromIter<T, I> for Rc<[T]> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, I: iter::TrustedLen<Item = T>> RcFromIter<T, I> for Rc<[T]> {
|
||||
impl<T, I: iter::TrustedLen<Item = T>> RcFromIter<T, I> for Rc<[T]> {
|
||||
default fn from_iter(iter: I) -> Self {
|
||||
// This is the case for a `TrustedLen` iterator.
|
||||
let (low, high) = iter.size_hint();
|
||||
if let Some(high) = high {
|
||||
debug_assert_eq!(
|
||||
low, high,
|
||||
low,
|
||||
high,
|
||||
"TrustedLen iterator's size hint is not exact: {:?}",
|
||||
(low, high)
|
||||
);
|
||||
|
@ -1641,9 +1614,7 @@ impl<T> Weak<T> {
|
|||
/// ```
|
||||
#[stable(feature = "downgraded_weak", since = "1.10.0")]
|
||||
pub fn new() -> Weak<T> {
|
||||
Weak {
|
||||
ptr: NonNull::new(usize::MAX as *mut RcBox<T>).expect("MAX is not 0"),
|
||||
}
|
||||
Weak { ptr: NonNull::new(usize::MAX as *mut RcBox<T>).expect("MAX is not 0") }
|
||||
}
|
||||
|
||||
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
|
||||
|
@ -1781,9 +1752,7 @@ impl<T> Weak<T> {
|
|||
let offset = data_offset(ptr);
|
||||
let fake_ptr = ptr as *mut RcBox<T>;
|
||||
let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
|
||||
Weak {
|
||||
ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw"),
|
||||
}
|
||||
Weak { ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1838,11 +1807,7 @@ impl<T: ?Sized> Weak<T> {
|
|||
/// [`Weak::new`]: #method.new
|
||||
#[stable(feature = "weak_counts", since = "1.41.0")]
|
||||
pub fn strong_count(&self) -> usize {
|
||||
if let Some(inner) = self.inner() {
|
||||
inner.strong()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
if let Some(inner) = self.inner() { inner.strong() } else { 0 }
|
||||
}
|
||||
|
||||
/// Gets the number of `Weak` pointers pointing to this allocation.
|
||||
|
@ -1850,24 +1815,22 @@ impl<T: ?Sized> Weak<T> {
|
|||
/// If no strong pointers remain, this will return zero.
|
||||
#[stable(feature = "weak_counts", since = "1.41.0")]
|
||||
pub fn weak_count(&self) -> usize {
|
||||
self.inner().map(|inner| {
|
||||
if inner.strong() > 0 {
|
||||
inner.weak() - 1 // subtract the implicit weak ptr
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}).unwrap_or(0)
|
||||
self.inner()
|
||||
.map(|inner| {
|
||||
if inner.strong() > 0 {
|
||||
inner.weak() - 1 // subtract the implicit weak ptr
|
||||
} else {
|
||||
0
|
||||
}
|
||||
})
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Returns `None` when the pointer is dangling and there is no allocated `RcBox`
|
||||
/// (i.e., when this `Weak` was created by `Weak::new`).
|
||||
#[inline]
|
||||
fn inner(&self) -> Option<&RcBox<T>> {
|
||||
if is_dangling(self.ptr) {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { self.ptr.as_ref() })
|
||||
}
|
||||
if is_dangling(self.ptr) { None } else { Some(unsafe { self.ptr.as_ref() }) }
|
||||
}
|
||||
|
||||
/// Returns `true` if the two `Weak`s point to the same allocation (similar to
|
||||
|
@ -2035,7 +1998,9 @@ trait RcBoxPtr<T: ?Sized> {
|
|||
// nevertheless, we insert an abort here to hint LLVM at
|
||||
// an otherwise missed optimization.
|
||||
if strong == 0 || strong == usize::max_value() {
|
||||
unsafe { abort(); }
|
||||
unsafe {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
self.inner().strong.set(strong + 1);
|
||||
}
|
||||
|
@ -2059,7 +2024,9 @@ trait RcBoxPtr<T: ?Sized> {
|
|||
// nevertheless, we insert an abort here to hint LLVM at
|
||||
// an otherwise missed optimization.
|
||||
if weak == 0 || weak == usize::max_value() {
|
||||
unsafe { abort(); }
|
||||
unsafe {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
self.inner().weak.set(weak + 1);
|
||||
}
|
||||
|
@ -2073,9 +2040,7 @@ trait RcBoxPtr<T: ?Sized> {
|
|||
impl<T: ?Sized> RcBoxPtr<T> for Rc<T> {
|
||||
#[inline(always)]
|
||||
fn inner(&self) -> &RcBox<T> {
|
||||
unsafe {
|
||||
self.ptr.as_ref()
|
||||
}
|
||||
unsafe { self.ptr.as_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2101,7 +2066,7 @@ impl<T: ?Sized> AsRef<T> for Rc<T> {
|
|||
}
|
||||
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<T: ?Sized> Unpin for Rc<T> { }
|
||||
impl<T: ?Sized> Unpin for Rc<T> {}
|
||||
|
||||
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
|
||||
// Align the unsized value to the end of the `RcBox`.
|
||||
|
|
|
@ -2,11 +2,11 @@ use super::*;
|
|||
|
||||
use std::boxed::Box;
|
||||
use std::cell::RefCell;
|
||||
use std::option::Option::{self, None, Some};
|
||||
use std::result::Result::{Err, Ok};
|
||||
use std::mem::drop;
|
||||
use std::clone::Clone;
|
||||
use std::convert::{From, TryInto};
|
||||
use std::mem::drop;
|
||||
use std::option::Option::{self, None, Some};
|
||||
use std::result::Result::{Err, Ok};
|
||||
|
||||
#[test]
|
||||
fn test_clone() {
|
||||
|
@ -341,11 +341,8 @@ fn test_clone_from_slice_panic() {
|
|||
}
|
||||
}
|
||||
|
||||
let s: &[Fail] = &[
|
||||
Fail(0, "foo".to_string()),
|
||||
Fail(1, "bar".to_string()),
|
||||
Fail(2, "baz".to_string()),
|
||||
];
|
||||
let s: &[Fail] =
|
||||
&[Fail(0, "foo".to_string()), Fail(1, "bar".to_string()), Fail(2, "baz".to_string())];
|
||||
|
||||
// Should panic, but not cause memory corruption
|
||||
let _r: Rc<[Fail]> = Rc::from(s);
|
||||
|
|
|
@ -23,16 +23,15 @@
|
|||
//! ```
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
// Many of the usings in this module are only used in the test configuration.
|
||||
// It's cleaner to just turn off the unused_imports warning than to fix them.
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use core::borrow::{Borrow, BorrowMut};
|
||||
use core::str::pattern::{Pattern, Searcher, ReverseSearcher, DoubleEndedSearcher};
|
||||
use core::iter::FusedIterator;
|
||||
use core::mem;
|
||||
use core::ptr;
|
||||
use core::iter::FusedIterator;
|
||||
use core::str::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher};
|
||||
use core::unicode::conversions;
|
||||
|
||||
use crate::borrow::ToOwned;
|
||||
|
@ -41,35 +40,35 @@ use crate::slice::{Concat, Join, SliceIndex};
|
|||
use crate::string::String;
|
||||
use crate::vec::Vec;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{FromStr, Utf8Error};
|
||||
#[allow(deprecated)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{Lines, LinesAny};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{Split, RSplit};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{SplitN, RSplitN};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{SplitTerminator, RSplitTerminator};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{Matches, RMatches};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{MatchIndices, RMatchIndices};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{from_utf8, from_utf8_mut, Chars, CharIndices, Bytes};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::SplitWhitespace;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::pattern;
|
||||
#[stable(feature = "encode_utf16", since = "1.8.0")]
|
||||
pub use core::str::EncodeUtf16;
|
||||
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
|
||||
pub use core::str::SplitAsciiWhitespace;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::SplitWhitespace;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{from_utf8, from_utf8_mut, Bytes, CharIndices, Chars};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError};
|
||||
#[stable(feature = "str_escape", since = "1.34.0")]
|
||||
pub use core::str::{EscapeDebug, EscapeDefault, EscapeUnicode};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{FromStr, Utf8Error};
|
||||
#[allow(deprecated)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{Lines, LinesAny};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{MatchIndices, RMatchIndices};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{Matches, RMatches};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{RSplit, Split};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{RSplitN, SplitN};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::str::{RSplitTerminator, SplitTerminator};
|
||||
|
||||
/// Note: `str` in `Concat<str>` is not meaningful here.
|
||||
/// This type parameter of the trait only exists to enable another impl.
|
||||
|
@ -87,9 +86,7 @@ impl<S: Borrow<str>> Join<&str> for [S] {
|
|||
type Output = String;
|
||||
|
||||
fn join(slice: &Self, sep: &str) -> String {
|
||||
unsafe {
|
||||
String::from_utf8_unchecked( join_generic_copy(slice, sep.as_bytes()) )
|
||||
}
|
||||
unsafe { String::from_utf8_unchecked(join_generic_copy(slice, sep.as_bytes())) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,10 +120,10 @@ macro_rules! spezialize_for_lengths {
|
|||
macro_rules! copy_slice_and_advance {
|
||||
($target:expr, $bytes:expr) => {
|
||||
let len = $bytes.len();
|
||||
let (head, tail) = {$target}.split_at_mut(len);
|
||||
let (head, tail) = { $target }.split_at_mut(len);
|
||||
head.copy_from_slice($bytes);
|
||||
$target = tail;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Optimized join implementation that works for both Vec<T> (T: Copy) and String's inner vec
|
||||
|
@ -156,11 +153,12 @@ where
|
|||
// if the `len` calculation overflows, we'll panic
|
||||
// we would have run out of memory anyway and the rest of the function requires
|
||||
// the entire Vec pre-allocated for safety
|
||||
let len = sep_len.checked_mul(iter.len()).and_then(|n| {
|
||||
slice.iter()
|
||||
.map(|s| s.borrow().as_ref().len())
|
||||
.try_fold(n, usize::checked_add)
|
||||
}).expect("attempt to join into collection with len > usize::MAX");
|
||||
let len = sep_len
|
||||
.checked_mul(iter.len())
|
||||
.and_then(|n| {
|
||||
slice.iter().map(|s| s.borrow().as_ref().len()).try_fold(n, usize::checked_add)
|
||||
})
|
||||
.expect("attempt to join into collection with len > usize::MAX");
|
||||
|
||||
// crucial for safety
|
||||
let mut result = Vec::with_capacity(len);
|
||||
|
@ -390,13 +388,13 @@ impl str {
|
|||
// See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
|
||||
// for the definition of `Final_Sigma`.
|
||||
debug_assert!('Σ'.len_utf8() == 2);
|
||||
let is_word_final = case_ignoreable_then_cased(from[..i].chars().rev()) &&
|
||||
!case_ignoreable_then_cased(from[i + 2..].chars());
|
||||
let is_word_final = case_ignoreable_then_cased(from[..i].chars().rev())
|
||||
&& !case_ignoreable_then_cased(from[i + 2..].chars());
|
||||
to.push_str(if is_word_final { "ς" } else { "σ" });
|
||||
}
|
||||
|
||||
fn case_ignoreable_then_cased<I: Iterator<Item = char>>(iter: I) -> bool {
|
||||
use core::unicode::derived_property::{Cased, Case_Ignorable};
|
||||
use core::unicode::derived_property::{Case_Ignorable, Cased};
|
||||
match iter.skip_while(|&c| Case_Ignorable(c)).next() {
|
||||
Some(c) => Cased(c),
|
||||
None => false,
|
||||
|
|
|
@ -50,15 +50,15 @@ use core::char::{decode_utf16, REPLACEMENT_CHARACTER};
|
|||
use core::fmt;
|
||||
use core::hash;
|
||||
use core::iter::{FromIterator, FusedIterator};
|
||||
use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeBounds};
|
||||
use core::ops::Bound::{Excluded, Included, Unbounded};
|
||||
use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeBounds};
|
||||
use core::ptr;
|
||||
use core::str::{pattern::Pattern, lossy};
|
||||
use core::str::{lossy, pattern::Pattern};
|
||||
|
||||
use crate::borrow::{Cow, ToOwned};
|
||||
use crate::collections::TryReserveError;
|
||||
use crate::boxed::Box;
|
||||
use crate::str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars};
|
||||
use crate::collections::TryReserveError;
|
||||
use crate::str::{self, from_boxed_utf8_unchecked, Chars, FromStr, Utf8Error};
|
||||
use crate::vec::Vec;
|
||||
|
||||
/// A UTF-8 encoded, growable string.
|
||||
|
@ -491,12 +491,7 @@ impl String {
|
|||
pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> {
|
||||
match str::from_utf8(&vec) {
|
||||
Ok(..) => Ok(String { vec }),
|
||||
Err(e) => {
|
||||
Err(FromUtf8Error {
|
||||
bytes: vec,
|
||||
error: e,
|
||||
})
|
||||
}
|
||||
Err(e) => Err(FromUtf8Error { bytes: vec, error: e }),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -985,7 +980,7 @@ impl String {
|
|||
/// }
|
||||
/// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?");
|
||||
/// ```
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
|
||||
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
|
||||
self.vec.try_reserve(additional)
|
||||
}
|
||||
|
@ -1023,8 +1018,8 @@ impl String {
|
|||
/// }
|
||||
/// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?");
|
||||
/// ```
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
|
||||
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
|
||||
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
|
||||
self.vec.try_reserve_exact(additional)
|
||||
}
|
||||
|
||||
|
@ -1072,7 +1067,7 @@ impl String {
|
|||
/// assert!(s.capacity() >= 3);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "shrink_to", reason = "new API", issue="56431")]
|
||||
#[unstable(feature = "shrink_to", reason = "new API", issue = "56431")]
|
||||
pub fn shrink_to(&mut self, min_capacity: usize) {
|
||||
self.vec.shrink_to(min_capacity)
|
||||
}
|
||||
|
@ -1222,9 +1217,7 @@ impl String {
|
|||
let next = idx + ch.len_utf8();
|
||||
let len = self.len();
|
||||
unsafe {
|
||||
ptr::copy(self.vec.as_ptr().add(next),
|
||||
self.vec.as_mut_ptr().add(idx),
|
||||
len - next);
|
||||
ptr::copy(self.vec.as_ptr().add(next), self.vec.as_mut_ptr().add(idx), len - next);
|
||||
self.vec.set_len(len - (next - idx));
|
||||
}
|
||||
ch
|
||||
|
@ -1258,25 +1251,26 @@ impl String {
|
|||
#[inline]
|
||||
#[stable(feature = "string_retain", since = "1.26.0")]
|
||||
pub fn retain<F>(&mut self, mut f: F)
|
||||
where F: FnMut(char) -> bool
|
||||
where
|
||||
F: FnMut(char) -> bool,
|
||||
{
|
||||
let len = self.len();
|
||||
let mut del_bytes = 0;
|
||||
let mut idx = 0;
|
||||
|
||||
while idx < len {
|
||||
let ch = unsafe {
|
||||
self.get_unchecked(idx..len).chars().next().unwrap()
|
||||
};
|
||||
let ch = unsafe { self.get_unchecked(idx..len).chars().next().unwrap() };
|
||||
let ch_len = ch.len_utf8();
|
||||
|
||||
if !f(ch) {
|
||||
del_bytes += ch_len;
|
||||
} else if del_bytes > 0 {
|
||||
unsafe {
|
||||
ptr::copy(self.vec.as_ptr().add(idx),
|
||||
self.vec.as_mut_ptr().add(idx - del_bytes),
|
||||
ch_len);
|
||||
ptr::copy(
|
||||
self.vec.as_ptr().add(idx),
|
||||
self.vec.as_mut_ptr().add(idx - del_bytes),
|
||||
ch_len,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1285,7 +1279,9 @@ impl String {
|
|||
}
|
||||
|
||||
if del_bytes > 0 {
|
||||
unsafe { self.vec.set_len(len - del_bytes); }
|
||||
unsafe {
|
||||
self.vec.set_len(len - del_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1331,12 +1327,8 @@ impl String {
|
|||
let amt = bytes.len();
|
||||
self.vec.reserve(amt);
|
||||
|
||||
ptr::copy(self.vec.as_ptr().add(idx),
|
||||
self.vec.as_mut_ptr().add(idx + amt),
|
||||
len - idx);
|
||||
ptr::copy(bytes.as_ptr(),
|
||||
self.vec.as_mut_ptr().add(idx),
|
||||
amt);
|
||||
ptr::copy(self.vec.as_ptr().add(idx), self.vec.as_mut_ptr().add(idx + amt), len - idx);
|
||||
ptr::copy(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt);
|
||||
self.vec.set_len(len + amt);
|
||||
}
|
||||
|
||||
|
@ -1531,7 +1523,8 @@ impl String {
|
|||
/// ```
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
pub fn drain<R>(&mut self, range: R) -> Drain<'_>
|
||||
where R: RangeBounds<usize>
|
||||
where
|
||||
R: RangeBounds<usize>,
|
||||
{
|
||||
// Memory safety
|
||||
//
|
||||
|
@ -1557,12 +1550,7 @@ impl String {
|
|||
// slicing does the appropriate bounds checks
|
||||
let chars_iter = self[start..end].chars();
|
||||
|
||||
Drain {
|
||||
start,
|
||||
end,
|
||||
iter: chars_iter,
|
||||
string: self_ptr,
|
||||
}
|
||||
Drain { start, end, iter: chars_iter, string: self_ptr }
|
||||
}
|
||||
|
||||
/// Removes the specified range in the string,
|
||||
|
@ -1591,7 +1579,8 @@ impl String {
|
|||
/// ```
|
||||
#[stable(feature = "splice", since = "1.27.0")]
|
||||
pub fn replace_range<R>(&mut self, range: R, replace_with: &str)
|
||||
where R: RangeBounds<usize>
|
||||
where
|
||||
R: RangeBounds<usize>,
|
||||
{
|
||||
// Memory safety
|
||||
//
|
||||
|
@ -1599,19 +1588,17 @@ impl String {
|
|||
// of the vector version. The data is just plain bytes.
|
||||
|
||||
match range.start_bound() {
|
||||
Included(&n) => assert!(self.is_char_boundary(n)),
|
||||
Excluded(&n) => assert!(self.is_char_boundary(n + 1)),
|
||||
Unbounded => {},
|
||||
Included(&n) => assert!(self.is_char_boundary(n)),
|
||||
Excluded(&n) => assert!(self.is_char_boundary(n + 1)),
|
||||
Unbounded => {}
|
||||
};
|
||||
match range.end_bound() {
|
||||
Included(&n) => assert!(self.is_char_boundary(n + 1)),
|
||||
Excluded(&n) => assert!(self.is_char_boundary(n)),
|
||||
Unbounded => {},
|
||||
Included(&n) => assert!(self.is_char_boundary(n + 1)),
|
||||
Excluded(&n) => assert!(self.is_char_boundary(n)),
|
||||
Unbounded => {}
|
||||
};
|
||||
|
||||
unsafe {
|
||||
self.as_mut_vec()
|
||||
}.splice(range, replace_with.bytes());
|
||||
unsafe { self.as_mut_vec() }.splice(range, replace_with.bytes());
|
||||
}
|
||||
|
||||
/// Converts this `String` into a [`Box`]`<`[`str`]`>`.
|
||||
|
@ -1840,9 +1827,11 @@ impl<'a> Extend<Cow<'a, str>> for String {
|
|||
}
|
||||
|
||||
/// A convenience impl that delegates to the impl for `&str`
|
||||
#[unstable(feature = "pattern",
|
||||
reason = "API not fully fleshed out and ready to be stabilized",
|
||||
issue = "27721")]
|
||||
#[unstable(
|
||||
feature = "pattern",
|
||||
reason = "API not fully fleshed out and ready to be stabilized",
|
||||
issue = "27721"
|
||||
)]
|
||||
impl<'a, 'b> Pattern<'a> for &'b String {
|
||||
type Searcher = <&'b str as Pattern<'a>>::Searcher;
|
||||
|
||||
|
@ -1879,21 +1868,28 @@ macro_rules! impl_eq {
|
|||
#[allow(unused_lifetimes)]
|
||||
impl<'a, 'b> PartialEq<$rhs> for $lhs {
|
||||
#[inline]
|
||||
fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&self[..], &other[..]) }
|
||||
fn eq(&self, other: &$rhs) -> bool {
|
||||
PartialEq::eq(&self[..], &other[..])
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&self[..], &other[..]) }
|
||||
fn ne(&self, other: &$rhs) -> bool {
|
||||
PartialEq::ne(&self[..], &other[..])
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(unused_lifetimes)]
|
||||
impl<'a, 'b> PartialEq<$lhs> for $rhs {
|
||||
#[inline]
|
||||
fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&self[..], &other[..]) }
|
||||
fn eq(&self, other: &$lhs) -> bool {
|
||||
PartialEq::eq(&self[..], &other[..])
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &$lhs) -> bool { PartialEq::ne(&self[..], &other[..]) }
|
||||
fn ne(&self, other: &$lhs) -> bool {
|
||||
PartialEq::ne(&self[..], &other[..])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_eq! { String, str }
|
||||
|
@ -2134,7 +2130,6 @@ impl FromStr for String {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// A trait for converting a value to a `String`.
|
||||
///
|
||||
/// This trait is automatically implemented for any type which implements the
|
||||
|
@ -2175,7 +2170,7 @@ impl<T: fmt::Display + ?Sized> ToString for T {
|
|||
use fmt::Write;
|
||||
let mut buf = String::new();
|
||||
buf.write_fmt(format_args!("{}", self))
|
||||
.expect("a Display implementation returned an error unexpectedly");
|
||||
.expect("a Display implementation returned an error unexpectedly");
|
||||
buf.shrink_to_fit();
|
||||
buf
|
||||
}
|
||||
|
|
|
@ -8,24 +8,24 @@
|
|||
|
||||
use core::any::Any;
|
||||
use core::array::LengthAtMost32;
|
||||
use core::sync::atomic;
|
||||
use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst};
|
||||
use core::borrow;
|
||||
use core::fmt;
|
||||
use core::cmp::Ordering;
|
||||
use core::iter;
|
||||
use core::convert::{From, TryFrom};
|
||||
use core::fmt;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::intrinsics::abort;
|
||||
use core::iter;
|
||||
use core::marker::{PhantomData, Unpin, Unsize};
|
||||
use core::mem::{self, align_of, align_of_val, size_of_val};
|
||||
use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn};
|
||||
use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver};
|
||||
use core::pin::Pin;
|
||||
use core::ptr::{self, NonNull};
|
||||
use core::marker::{Unpin, Unsize, PhantomData};
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::{isize, usize};
|
||||
use core::convert::{From, TryFrom};
|
||||
use core::slice::{self, from_raw_parts_mut};
|
||||
use core::sync::atomic;
|
||||
use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst};
|
||||
use core::{isize, usize};
|
||||
|
||||
use crate::alloc::{Global, Alloc, Layout, box_free, handle_alloc_error};
|
||||
use crate::alloc::{box_free, handle_alloc_error, Alloc, Global, Layout};
|
||||
use crate::boxed::Box;
|
||||
use crate::rc::is_dangling;
|
||||
use crate::string::String;
|
||||
|
@ -211,10 +211,7 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Arc<U>> for Arc<T> {}
|
|||
|
||||
impl<T: ?Sized> Arc<T> {
|
||||
fn from_inner(ptr: NonNull<ArcInner<T>>) -> Self {
|
||||
Self {
|
||||
ptr,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
Self { ptr, phantom: PhantomData }
|
||||
}
|
||||
|
||||
unsafe fn from_ptr(ptr: *mut ArcInner<T>) -> Self {
|
||||
|
@ -334,10 +331,9 @@ impl<T> Arc<T> {
|
|||
#[unstable(feature = "new_uninit", issue = "63291")]
|
||||
pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> {
|
||||
unsafe {
|
||||
Arc::from_ptr(Arc::allocate_for_layout(
|
||||
Layout::new::<T>(),
|
||||
|mem| mem as *mut ArcInner<mem::MaybeUninit<T>>,
|
||||
))
|
||||
Arc::from_ptr(Arc::allocate_for_layout(Layout::new::<T>(), |mem| {
|
||||
mem as *mut ArcInner<mem::MaybeUninit<T>>
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -446,9 +442,7 @@ impl<T> Arc<[T]> {
|
|||
/// ```
|
||||
#[unstable(feature = "new_uninit", issue = "63291")]
|
||||
pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
|
||||
unsafe {
|
||||
Arc::from_ptr(Arc::allocate_for_slice(len))
|
||||
}
|
||||
unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -772,18 +766,15 @@ impl<T: ?Sized> Arc<T> {
|
|||
/// and must return back a (potentially fat)-pointer for the `ArcInner<T>`.
|
||||
unsafe fn allocate_for_layout(
|
||||
value_layout: Layout,
|
||||
mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T>
|
||||
mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T>,
|
||||
) -> *mut ArcInner<T> {
|
||||
// Calculate layout using the given value layout.
|
||||
// Previously, layout was calculated on the expression
|
||||
// `&*(ptr as *const ArcInner<T>)`, but this created a misaligned
|
||||
// reference (see #54908).
|
||||
let layout = Layout::new::<ArcInner<()>>()
|
||||
.extend(value_layout).unwrap().0
|
||||
.pad_to_align();
|
||||
let layout = Layout::new::<ArcInner<()>>().extend(value_layout).unwrap().0.pad_to_align();
|
||||
|
||||
let mem = Global.alloc(layout)
|
||||
.unwrap_or_else(|_| handle_alloc_error(layout));
|
||||
let mem = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
|
||||
|
||||
// Initialize the ArcInner
|
||||
let inner = mem_to_arcinner(mem.as_ptr());
|
||||
|
@ -798,10 +789,9 @@ impl<T: ?Sized> Arc<T> {
|
|||
/// Allocates an `ArcInner<T>` with sufficient space for an unsized inner value.
|
||||
unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> {
|
||||
// Allocate for the `ArcInner<T>` using the given value.
|
||||
Self::allocate_for_layout(
|
||||
Layout::for_value(&*ptr),
|
||||
|mem| set_data_ptr(ptr as *mut T, mem) as *mut ArcInner<T>,
|
||||
)
|
||||
Self::allocate_for_layout(Layout::for_value(&*ptr), |mem| {
|
||||
set_data_ptr(ptr as *mut T, mem) as *mut ArcInner<T>
|
||||
})
|
||||
}
|
||||
|
||||
fn from_box(v: Box<T>) -> Arc<T> {
|
||||
|
@ -816,7 +806,8 @@ impl<T: ?Sized> Arc<T> {
|
|||
ptr::copy_nonoverlapping(
|
||||
bptr as *const T as *const u8,
|
||||
&mut (*ptr).data as *mut _ as *mut u8,
|
||||
value_size);
|
||||
value_size,
|
||||
);
|
||||
|
||||
// Free the allocation without dropping its contents
|
||||
box_free(box_unique);
|
||||
|
@ -829,10 +820,9 @@ impl<T: ?Sized> Arc<T> {
|
|||
impl<T> Arc<[T]> {
|
||||
/// Allocates an `ArcInner<[T]>` with the given length.
|
||||
unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> {
|
||||
Self::allocate_for_layout(
|
||||
Layout::array::<T>(len).unwrap(),
|
||||
|mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut ArcInner<[T]>,
|
||||
)
|
||||
Self::allocate_for_layout(Layout::array::<T>(len).unwrap(), |mem| {
|
||||
ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut ArcInner<[T]>
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -852,10 +842,7 @@ impl<T> Arc<[T]> {
|
|||
unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> {
|
||||
let ptr = Self::allocate_for_slice(v.len());
|
||||
|
||||
ptr::copy_nonoverlapping(
|
||||
v.as_ptr(),
|
||||
&mut (*ptr).data as *mut [T] as *mut T,
|
||||
v.len());
|
||||
ptr::copy_nonoverlapping(v.as_ptr(), &mut (*ptr).data as *mut [T] as *mut T, v.len());
|
||||
|
||||
Self::from_ptr(ptr)
|
||||
}
|
||||
|
@ -893,12 +880,7 @@ impl<T> Arc<[T]> {
|
|||
// Pointer to first element
|
||||
let elems = &mut (*ptr).data as *mut [T] as *mut T;
|
||||
|
||||
let mut guard = Guard {
|
||||
mem: NonNull::new_unchecked(mem),
|
||||
elems,
|
||||
layout,
|
||||
n_elems: 0,
|
||||
};
|
||||
let mut guard = Guard { mem: NonNull::new_unchecked(mem), elems, layout, n_elems: 0 };
|
||||
|
||||
for (i, item) in iter.enumerate() {
|
||||
ptr::write(elems.add(i), item);
|
||||
|
@ -920,9 +902,7 @@ trait ArcFromSlice<T> {
|
|||
impl<T: Clone> ArcFromSlice<T> for Arc<[T]> {
|
||||
#[inline]
|
||||
default fn from_slice(v: &[T]) -> Self {
|
||||
unsafe {
|
||||
Self::from_iter_exact(v.iter().cloned(), v.len())
|
||||
}
|
||||
unsafe { Self::from_iter_exact(v.iter().cloned(), v.len()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1079,9 +1059,7 @@ impl<T: Clone> Arc<T> {
|
|||
|
||||
// As with `get_mut()`, the unsafety is ok because our reference was
|
||||
// either unique to begin with, or became one upon cloning the contents.
|
||||
unsafe {
|
||||
&mut this.ptr.as_mut().data
|
||||
}
|
||||
unsafe { &mut this.ptr.as_mut().data }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1121,9 +1099,7 @@ impl<T: ?Sized> Arc<T> {
|
|||
// reference count is guaranteed to be 1 at this point, and we required
|
||||
// the Arc itself to be `mut`, so we're returning the only possible
|
||||
// reference to the inner data.
|
||||
unsafe {
|
||||
Some(Arc::get_mut_unchecked(this))
|
||||
}
|
||||
unsafe { Some(Arc::get_mut_unchecked(this)) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -1317,9 +1293,7 @@ impl<T> Weak<T> {
|
|||
/// ```
|
||||
#[stable(feature = "downgraded_weak", since = "1.10.0")]
|
||||
pub fn new() -> Weak<T> {
|
||||
Weak {
|
||||
ptr: NonNull::new(usize::MAX as *mut ArcInner<T>).expect("MAX is not 0"),
|
||||
}
|
||||
Weak { ptr: NonNull::new(usize::MAX as *mut ArcInner<T>).expect("MAX is not 0") }
|
||||
}
|
||||
|
||||
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
|
||||
|
@ -1458,9 +1432,7 @@ impl<T> Weak<T> {
|
|||
let offset = data_offset(ptr);
|
||||
let fake_ptr = ptr as *mut ArcInner<T>;
|
||||
let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
|
||||
Weak {
|
||||
ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw"),
|
||||
}
|
||||
Weak { ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1531,11 +1503,7 @@ impl<T: ?Sized> Weak<T> {
|
|||
/// [`Weak::new`]: #method.new
|
||||
#[stable(feature = "weak_counts", since = "1.41.0")]
|
||||
pub fn strong_count(&self) -> usize {
|
||||
if let Some(inner) = self.inner() {
|
||||
inner.strong.load(SeqCst)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
if let Some(inner) = self.inner() { inner.strong.load(SeqCst) } else { 0 }
|
||||
}
|
||||
|
||||
/// Gets an approximation of the number of `Weak` pointers pointing to this
|
||||
|
@ -1553,31 +1521,29 @@ impl<T: ?Sized> Weak<T> {
|
|||
/// [`Weak::new`]: #method.new
|
||||
#[stable(feature = "weak_counts", since = "1.41.0")]
|
||||
pub fn weak_count(&self) -> usize {
|
||||
self.inner().map(|inner| {
|
||||
let weak = inner.weak.load(SeqCst);
|
||||
let strong = inner.strong.load(SeqCst);
|
||||
if strong == 0 {
|
||||
0
|
||||
} else {
|
||||
// Since we observed that there was at least one strong pointer
|
||||
// after reading the weak count, we know that the implicit weak
|
||||
// reference (present whenever any strong references are alive)
|
||||
// was still around when we observed the weak count, and can
|
||||
// therefore safely subtract it.
|
||||
weak - 1
|
||||
}
|
||||
}).unwrap_or(0)
|
||||
self.inner()
|
||||
.map(|inner| {
|
||||
let weak = inner.weak.load(SeqCst);
|
||||
let strong = inner.strong.load(SeqCst);
|
||||
if strong == 0 {
|
||||
0
|
||||
} else {
|
||||
// Since we observed that there was at least one strong pointer
|
||||
// after reading the weak count, we know that the implicit weak
|
||||
// reference (present whenever any strong references are alive)
|
||||
// was still around when we observed the weak count, and can
|
||||
// therefore safely subtract it.
|
||||
weak - 1
|
||||
}
|
||||
})
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Returns `None` when the pointer is dangling and there is no allocated `ArcInner`,
|
||||
/// (i.e., when this `Weak` was created by `Weak::new`).
|
||||
#[inline]
|
||||
fn inner(&self) -> Option<&ArcInner<T>> {
|
||||
if is_dangling(self.ptr) {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { self.ptr.as_ref() })
|
||||
}
|
||||
if is_dangling(self.ptr) { None } else { Some(unsafe { self.ptr.as_ref() }) }
|
||||
}
|
||||
|
||||
/// Returns `true` if the two `Weak`s point to the same allocation (similar to
|
||||
|
@ -1722,17 +1688,11 @@ impl<T: ?Sized> Drop for Weak<T> {
|
|||
// weak count can only be locked if there was precisely one weak ref,
|
||||
// meaning that drop could only subsequently run ON that remaining weak
|
||||
// ref, which can only happen after the lock is released.
|
||||
let inner = if let Some(inner) = self.inner() {
|
||||
inner
|
||||
} else {
|
||||
return
|
||||
};
|
||||
let inner = if let Some(inner) = self.inner() { inner } else { return };
|
||||
|
||||
if inner.weak.fetch_sub(1, Release) == 1 {
|
||||
atomic::fence(Acquire);
|
||||
unsafe {
|
||||
Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref()))
|
||||
}
|
||||
unsafe { Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2110,7 +2070,8 @@ impl<T, I: iter::TrustedLen<Item = T>> ArcFromIter<T, I> for Arc<[T]> {
|
|||
let (low, high) = iter.size_hint();
|
||||
if let Some(high) = high {
|
||||
debug_assert_eq!(
|
||||
low, high,
|
||||
low,
|
||||
high,
|
||||
"TrustedLen iterator's size hint is not exact: {:?}",
|
||||
(low, high)
|
||||
);
|
||||
|
@ -2155,7 +2116,7 @@ impl<T: ?Sized> AsRef<T> for Arc<T> {
|
|||
}
|
||||
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<T: ?Sized> Unpin for Arc<T> { }
|
||||
impl<T: ?Sized> Unpin for Arc<T> {}
|
||||
|
||||
/// Computes the offset of the data field within `ArcInner`.
|
||||
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
|
||||
|
|
|
@ -2,14 +2,17 @@ use super::*;
|
|||
|
||||
use std::boxed::Box;
|
||||
use std::clone::Clone;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::convert::{From, TryInto};
|
||||
use std::mem::drop;
|
||||
use std::ops::Drop;
|
||||
use std::option::Option::{self, None, Some};
|
||||
use std::sync::atomic::{self, Ordering::{Acquire, SeqCst}};
|
||||
use std::thread;
|
||||
use std::sync::atomic::{
|
||||
self,
|
||||
Ordering::{Acquire, SeqCst},
|
||||
};
|
||||
use std::sync::mpsc::channel;
|
||||
use std::sync::Mutex;
|
||||
use std::convert::{From, TryInto};
|
||||
use std::thread;
|
||||
|
||||
use crate::vec::Vec;
|
||||
|
||||
|
@ -394,11 +397,8 @@ fn test_clone_from_slice_panic() {
|
|||
}
|
||||
}
|
||||
|
||||
let s: &[Fail] = &[
|
||||
Fail(0, "foo".to_string()),
|
||||
Fail(1, "bar".to_string()),
|
||||
Fail(2, "baz".to_string()),
|
||||
];
|
||||
let s: &[Fail] =
|
||||
&[Fail(0, "foo".to_string()), Fail(1, "bar".to_string()), Fail(2, "baz".to_string())];
|
||||
|
||||
// Should panic, but not cause memory corruption
|
||||
let _r: Arc<[Fail]> = Arc::from(s);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use std::collections::BinaryHeap;
|
||||
use std::collections::binary_heap::{Drain, PeekMut};
|
||||
use std::collections::BinaryHeap;
|
||||
use std::iter::TrustedLen;
|
||||
|
||||
#[test]
|
||||
|
@ -349,10 +349,10 @@ fn assert_covariance() {
|
|||
#[test]
|
||||
#[cfg(not(target_os = "emscripten"))]
|
||||
fn panic_safe() {
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
use std::cmp;
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use rand::{thread_rng, seq::SliceRandom};
|
||||
|
||||
static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
|
@ -389,10 +389,8 @@ fn panic_safe() {
|
|||
for i in 1..=DATASZ {
|
||||
DROP_COUNTER.store(0, Ordering::SeqCst);
|
||||
|
||||
let mut panic_ords: Vec<_> = data.iter()
|
||||
.filter(|&&x| x != i)
|
||||
.map(|&x| PanicOrd(x, false))
|
||||
.collect();
|
||||
let mut panic_ords: Vec<_> =
|
||||
data.iter().filter(|&&x| x != i).map(|&x| PanicOrd(x, false)).collect();
|
||||
let panic_item = PanicOrd(i, true);
|
||||
|
||||
// heapify the sane items
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::collections::btree_map::Entry::{Occupied, Vacant};
|
||||
use std::collections::BTreeMap;
|
||||
use std::iter::FromIterator;
|
||||
use std::ops::Bound::{self, Excluded, Included, Unbounded};
|
||||
use std::rc::Rc;
|
||||
use std::iter::FromIterator;
|
||||
|
||||
use super::DeterministicRng;
|
||||
|
||||
|
@ -101,7 +101,8 @@ fn test_iter() {
|
|||
let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
|
||||
|
||||
fn test<T>(size: usize, mut iter: T)
|
||||
where T: Iterator<Item = (usize, usize)>
|
||||
where
|
||||
T: Iterator<Item = (usize, usize)>,
|
||||
{
|
||||
for i in 0..size {
|
||||
assert_eq!(iter.size_hint(), (size - i, Some(size - i)));
|
||||
|
@ -126,7 +127,8 @@ fn test_iter_rev() {
|
|||
let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
|
||||
|
||||
fn test<T>(size: usize, mut iter: T)
|
||||
where T: Iterator<Item = (usize, usize)>
|
||||
where
|
||||
T: Iterator<Item = (usize, usize)>,
|
||||
{
|
||||
for i in 0..size {
|
||||
assert_eq!(iter.size_hint(), (size - i, Some(size - i)));
|
||||
|
@ -165,7 +167,8 @@ fn test_iter_mixed() {
|
|||
let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
|
||||
|
||||
fn test<T>(size: usize, mut iter: T)
|
||||
where T: Iterator<Item = (usize, usize)> + DoubleEndedIterator
|
||||
where
|
||||
T: Iterator<Item = (usize, usize)> + DoubleEndedIterator,
|
||||
{
|
||||
for i in 0..size / 4 {
|
||||
assert_eq!(iter.size_hint(), (size - i * 2, Some(size - i * 2)));
|
||||
|
@ -207,8 +210,9 @@ fn test_range_inclusive() {
|
|||
let map: BTreeMap<_, _> = (0..=size).map(|i| (i, i)).collect();
|
||||
|
||||
fn check<'a, L, R>(lhs: L, rhs: R)
|
||||
where L: IntoIterator<Item=(&'a i32, &'a i32)>,
|
||||
R: IntoIterator<Item=(&'a i32, &'a i32)>,
|
||||
where
|
||||
L: IntoIterator<Item = (&'a i32, &'a i32)>,
|
||||
R: IntoIterator<Item = (&'a i32, &'a i32)>,
|
||||
{
|
||||
let lhs: Vec<_> = lhs.into_iter().collect();
|
||||
let rhs: Vec<_> = rhs.into_iter().collect();
|
||||
|
@ -313,7 +317,7 @@ fn test_range_borrowed_key() {
|
|||
map.insert("coyote".to_string(), 3);
|
||||
map.insert("dingo".to_string(), 4);
|
||||
// NOTE: would like to use simply "b".."d" here...
|
||||
let mut iter = map.range::<str, _>((Included("b"),Excluded("d")));
|
||||
let mut iter = map.range::<str, _>((Included("b"), Excluded("d")));
|
||||
assert_eq!(iter.next(), Some((&"baboon".to_string(), &2)));
|
||||
assert_eq!(iter.next(), Some((&"coyote".to_string(), &3)));
|
||||
assert_eq!(iter.next(), None);
|
||||
|
@ -408,7 +412,6 @@ fn test_entry() {
|
|||
assert_eq!(map.get(&1).unwrap(), &100);
|
||||
assert_eq!(map.len(), 6);
|
||||
|
||||
|
||||
// Existing key (update)
|
||||
match map.entry(2) {
|
||||
Vacant(_) => unreachable!(),
|
||||
|
@ -430,7 +433,6 @@ fn test_entry() {
|
|||
assert_eq!(map.get(&3), None);
|
||||
assert_eq!(map.len(), 5);
|
||||
|
||||
|
||||
// Inexistent key (insert)
|
||||
match map.entry(10) {
|
||||
Occupied(_) => unreachable!(),
|
||||
|
@ -555,7 +557,7 @@ fn test_clone() {
|
|||
#[test]
|
||||
#[allow(dead_code)]
|
||||
fn test_variance() {
|
||||
use std::collections::btree_map::{Iter, IntoIter, Range, Keys, Values};
|
||||
use std::collections::btree_map::{IntoIter, Iter, Keys, Range, Values};
|
||||
|
||||
fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> {
|
||||
v
|
||||
|
@ -649,7 +651,6 @@ fn test_first_last_entry() {
|
|||
assert_eq!(a.last_entry().unwrap().key(), &1);
|
||||
}
|
||||
|
||||
|
||||
macro_rules! create_append_test {
|
||||
($name:ident, $len:expr) => {
|
||||
#[test]
|
||||
|
@ -661,7 +662,7 @@ macro_rules! create_append_test {
|
|||
|
||||
let mut b = BTreeMap::new();
|
||||
for i in 5..$len {
|
||||
b.insert(i, 2*i);
|
||||
b.insert(i, 2 * i);
|
||||
}
|
||||
|
||||
a.append(&mut b);
|
||||
|
@ -673,12 +674,12 @@ macro_rules! create_append_test {
|
|||
if i < 5 {
|
||||
assert_eq!(a[&i], i);
|
||||
} else {
|
||||
assert_eq!(a[&i], 2*i);
|
||||
assert_eq!(a[&i], 2 * i);
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(a.remove(&($len-1)), Some(2*($len-1)));
|
||||
assert_eq!(a.insert($len-1, 20), None);
|
||||
assert_eq!(a.remove(&($len - 1)), Some(2 * ($len - 1)));
|
||||
assert_eq!(a.insert($len - 1, 20), None);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -32,7 +32,8 @@ fn test_hash() {
|
|||
}
|
||||
|
||||
fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F)
|
||||
where F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, &mut dyn FnMut(&i32) -> bool) -> bool
|
||||
where
|
||||
F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, &mut dyn FnMut(&i32) -> bool) -> bool,
|
||||
{
|
||||
let mut set_a = BTreeSet::new();
|
||||
let mut set_b = BTreeSet::new();
|
||||
|
@ -45,15 +46,13 @@ fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F)
|
|||
}
|
||||
|
||||
let mut i = 0;
|
||||
f(&set_a,
|
||||
&set_b,
|
||||
&mut |&x| {
|
||||
if i < expected.len() {
|
||||
assert_eq!(x, expected[i]);
|
||||
}
|
||||
i += 1;
|
||||
true
|
||||
});
|
||||
f(&set_a, &set_b, &mut |&x| {
|
||||
if i < expected.len() {
|
||||
assert_eq!(x, expected[i]);
|
||||
}
|
||||
i += 1;
|
||||
true
|
||||
});
|
||||
assert_eq!(i, expected.len());
|
||||
}
|
||||
|
||||
|
@ -68,11 +67,10 @@ fn test_intersection() {
|
|||
check_intersection(&[], &[1, 2, 3], &[]);
|
||||
check_intersection(&[2], &[1, 2, 3], &[2]);
|
||||
check_intersection(&[1, 2, 3], &[2], &[2]);
|
||||
check_intersection(&[11, 1, 3, 77, 103, 5, -5],
|
||||
&[2, 11, 77, -9, -42, 5, 3],
|
||||
&[3, 5, 11, 77]);
|
||||
check_intersection(&[11, 1, 3, 77, 103, 5, -5], &[2, 11, 77, -9, -42, 5, 3], &[3, 5, 11, 77]);
|
||||
|
||||
if cfg!(miri) { // Miri is too slow
|
||||
if cfg!(miri) {
|
||||
// Miri is too slow
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -87,9 +85,7 @@ fn test_intersection() {
|
|||
check_intersection(&large, &[99], &[99]);
|
||||
check_intersection(&[100], &large, &[]);
|
||||
check_intersection(&large, &[100], &[]);
|
||||
check_intersection(&[11, 5000, 1, 3, 77, 8924],
|
||||
&large,
|
||||
&[1, 3, 11, 77]);
|
||||
check_intersection(&[11, 5000, 1, 3, 77, 8924], &large, &[1, 3, 11, 77]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -121,11 +117,14 @@ fn test_difference() {
|
|||
check_difference(&[1, 3, 5, 9, 11], &[3, 6, 9], &[1, 5, 11]);
|
||||
check_difference(&[1, 3, 5, 9, 11], &[0, 1], &[3, 5, 9, 11]);
|
||||
check_difference(&[1, 3, 5, 9, 11], &[11, 12], &[1, 3, 5, 9]);
|
||||
check_difference(&[-5, 11, 22, 33, 40, 42],
|
||||
&[-12, -5, 14, 23, 34, 38, 39, 50],
|
||||
&[11, 22, 33, 40, 42]);
|
||||
check_difference(
|
||||
&[-5, 11, 22, 33, 40, 42],
|
||||
&[-12, -5, 14, 23, 34, 38, 39, 50],
|
||||
&[11, 22, 33, 40, 42],
|
||||
);
|
||||
|
||||
if cfg!(miri) { // Miri is too slow
|
||||
if cfg!(miri) {
|
||||
// Miri is too slow
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -135,9 +134,7 @@ fn test_difference() {
|
|||
check_difference(&[0], &large, &[]);
|
||||
check_difference(&[99], &large, &[]);
|
||||
check_difference(&[100], &large, &[100]);
|
||||
check_difference(&[11, 5000, 1, 3, 77, 8924],
|
||||
&large,
|
||||
&[5000, 8924]);
|
||||
check_difference(&[11, 5000, 1, 3, 77, 8924], &large, &[5000, 8924]);
|
||||
check_difference(&large, &[], &large);
|
||||
check_difference(&large, &[-1], &large);
|
||||
check_difference(&large, &[100], &large);
|
||||
|
@ -216,9 +213,7 @@ fn test_symmetric_difference() {
|
|||
check_symmetric_difference(&[], &[], &[]);
|
||||
check_symmetric_difference(&[1, 2, 3], &[2], &[1, 3]);
|
||||
check_symmetric_difference(&[2], &[1, 2, 3], &[1, 3]);
|
||||
check_symmetric_difference(&[1, 3, 5, 9, 11],
|
||||
&[-2, 3, 9, 14, 22],
|
||||
&[-2, 1, 5, 11, 14, 22]);
|
||||
check_symmetric_difference(&[1, 3, 5, 9, 11], &[-2, 3, 9, 14, 22], &[-2, 1, 5, 11, 14, 22]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -242,9 +237,11 @@ fn test_union() {
|
|||
check_union(&[], &[], &[]);
|
||||
check_union(&[1, 2, 3], &[2], &[1, 2, 3]);
|
||||
check_union(&[2], &[1, 2, 3], &[1, 2, 3]);
|
||||
check_union(&[1, 3, 5, 9, 11, 16, 19, 24],
|
||||
&[-2, 1, 5, 9, 13, 19],
|
||||
&[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]);
|
||||
check_union(
|
||||
&[1, 3, 5, 9, 11, 16, 19, 24],
|
||||
&[-2, 1, 5, 9, 13, 19],
|
||||
&[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -285,14 +282,14 @@ fn test_is_subset() {
|
|||
assert_eq!(is_subset(&[1, 2], &[1]), false);
|
||||
assert_eq!(is_subset(&[1, 2], &[1, 2]), true);
|
||||
assert_eq!(is_subset(&[1, 2], &[2, 3]), false);
|
||||
assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42],
|
||||
&[-12, -5, 11, 14, 22, 23, 33, 34, 38, 39, 40, 42]),
|
||||
true);
|
||||
assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42],
|
||||
&[-12, -5, 11, 14, 22, 23, 34, 38]),
|
||||
false);
|
||||
assert_eq!(
|
||||
is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 33, 34, 38, 39, 40, 42]),
|
||||
true
|
||||
);
|
||||
assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 34, 38]), false);
|
||||
|
||||
if cfg!(miri) { // Miri is too slow
|
||||
if cfg!(miri) {
|
||||
// Miri is too slow
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::alloc::{Global, Alloc, Layout, System};
|
||||
use std::alloc::{Alloc, Global, Layout, System};
|
||||
|
||||
/// Issue #45955 and #62251.
|
||||
#[test]
|
||||
|
@ -12,16 +12,23 @@ fn std_heap_overaligned_request() {
|
|||
}
|
||||
|
||||
fn check_overalign_requests<T: Alloc>(mut allocator: T) {
|
||||
for &align in &[4, 8, 16, 32] { // less than and bigger than `MIN_ALIGN`
|
||||
for &size in &[align/2, align-1] { // size less than alignment
|
||||
for &align in &[4, 8, 16, 32] {
|
||||
// less than and bigger than `MIN_ALIGN`
|
||||
for &size in &[align / 2, align - 1] {
|
||||
// size less than alignment
|
||||
let iterations = 128;
|
||||
unsafe {
|
||||
let pointers: Vec<_> = (0..iterations).map(|_| {
|
||||
allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap()
|
||||
}).collect();
|
||||
let pointers: Vec<_> = (0..iterations)
|
||||
.map(|_| {
|
||||
allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap()
|
||||
})
|
||||
.collect();
|
||||
for &ptr in &pointers {
|
||||
assert_eq!((ptr.as_ptr() as usize) % align, 0,
|
||||
"Got a pointer less aligned than requested")
|
||||
assert_eq!(
|
||||
(ptr.as_ptr() as usize) % align,
|
||||
0,
|
||||
"Got a pointer less aligned than requested"
|
||||
)
|
||||
}
|
||||
|
||||
// Clean up
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
#![feature(binary_heap_into_iter_sorted)]
|
||||
#![feature(binary_heap_drain_sorted)]
|
||||
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
mod arc;
|
||||
mod binary_heap;
|
||||
|
@ -27,8 +27,8 @@ mod rc;
|
|||
mod slice;
|
||||
mod str;
|
||||
mod string;
|
||||
mod vec_deque;
|
||||
mod vec;
|
||||
mod vec_deque;
|
||||
|
||||
fn hash<T: Hash>(t: &T) -> u64 {
|
||||
let mut s = DefaultHasher::new();
|
||||
|
|
|
@ -531,7 +531,6 @@ fn drain_filter_complex() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_drop() {
|
||||
static mut DROPS: i32 = 0;
|
||||
|
|
|
@ -3,11 +3,11 @@ use std::cmp::Ordering::{self, Equal, Greater, Less};
|
|||
use std::mem;
|
||||
use std::panic;
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::{Ordering::Relaxed, AtomicUsize};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
|
||||
|
||||
use rand::{Rng, RngCore, thread_rng};
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::distributions::Standard;
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::{thread_rng, Rng, RngCore};
|
||||
|
||||
fn square(n: usize) -> usize {
|
||||
n * n
|
||||
|
@ -231,7 +231,6 @@ fn test_slice_to() {
|
|||
assert_eq!(&vec[..0], b);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_pop() {
|
||||
let mut v = vec![5];
|
||||
|
@ -395,10 +394,8 @@ fn test_sort() {
|
|||
for len in (2..25).chain(500..510) {
|
||||
for &modulus in &[5, 10, 100, 1000] {
|
||||
for _ in 0..10 {
|
||||
let orig: Vec<_> = rng.sample_iter::<i32, _>(&Standard)
|
||||
.map(|x| x % modulus)
|
||||
.take(len)
|
||||
.collect();
|
||||
let orig: Vec<_> =
|
||||
rng.sample_iter::<i32, _>(&Standard).map(|x| x % modulus).take(len).collect();
|
||||
|
||||
// Sort in default order.
|
||||
let mut v = orig.clone();
|
||||
|
@ -543,7 +540,7 @@ fn test_rotate_left() {
|
|||
|
||||
// non-small prime rotation, has a few rounds of swapping
|
||||
v = (389..1000).chain(0..389).collect();
|
||||
v.rotate_left(1000-389);
|
||||
v.rotate_left(1000 - 389);
|
||||
assert_eq!(v, expected);
|
||||
}
|
||||
|
||||
|
@ -697,7 +694,7 @@ macro_rules! assert_order {
|
|||
(Equal, $a:expr, $b:expr) => {
|
||||
assert_eq!($a.cmp($b), Equal);
|
||||
assert_eq!($a, $b);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -714,7 +711,6 @@ fn test_total_ord_u8() {
|
|||
assert_order!(Greater, &[2u8, 2][..], &c[..]);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_total_ord_i32() {
|
||||
let c = &[1, 2, 3];
|
||||
|
@ -804,7 +800,6 @@ fn test_mut_iterator() {
|
|||
|
||||
#[test]
|
||||
fn test_rev_iterator() {
|
||||
|
||||
let xs = [1, 2, 5, 10, 11];
|
||||
let ys = [11, 10, 5, 2, 1];
|
||||
let mut i = 0;
|
||||
|
@ -827,15 +822,13 @@ fn test_mut_rev_iterator() {
|
|||
#[test]
|
||||
fn test_move_iterator() {
|
||||
let xs = vec![1, 2, 3, 4, 5];
|
||||
assert_eq!(xs.into_iter().fold(0, |a: usize, b: usize| 10 * a + b),
|
||||
12345);
|
||||
assert_eq!(xs.into_iter().fold(0, |a: usize, b: usize| 10 * a + b), 12345);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_move_rev_iterator() {
|
||||
let xs = vec![1, 2, 3, 4, 5];
|
||||
assert_eq!(xs.into_iter().rev().fold(0, |a: usize, b: usize| 10 * a + b),
|
||||
54321);
|
||||
assert_eq!(xs.into_iter().rev().fold(0, |a: usize, b: usize| 10 * a + b), 54321);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -879,11 +872,9 @@ fn test_splitnator_mut() {
|
|||
let xs = &mut [1, 2, 3, 4, 5];
|
||||
|
||||
let splits: &[&mut [_]] = &[&mut [1, 2, 3, 4, 5]];
|
||||
assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::<Vec<_>>(),
|
||||
splits);
|
||||
assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::<Vec<_>>(), splits);
|
||||
let splits: &[&mut [_]] = &[&mut [1], &mut [3, 4, 5]];
|
||||
assert_eq!(xs.splitn_mut(2, |x| *x % 2 == 0).collect::<Vec<_>>(),
|
||||
splits);
|
||||
assert_eq!(xs.splitn_mut(2, |x| *x % 2 == 0).collect::<Vec<_>>(), splits);
|
||||
let splits: &[&mut [_]] = &[&mut [], &mut [], &mut [], &mut [4, 5]];
|
||||
assert_eq!(xs.splitn_mut(4, |_| true).collect::<Vec<_>>(), splits);
|
||||
|
||||
|
@ -1055,11 +1046,11 @@ fn test_reverse_part() {
|
|||
#[test]
|
||||
fn test_show() {
|
||||
macro_rules! test_show_vec {
|
||||
($x:expr, $x_str:expr) => ({
|
||||
($x:expr, $x_str:expr) => {{
|
||||
let (x, x_str) = ($x, $x_str);
|
||||
assert_eq!(format!("{:?}", x), x_str);
|
||||
assert_eq!(format!("{:?}", x), x_str);
|
||||
})
|
||||
}};
|
||||
}
|
||||
let empty = Vec::<i32>::new();
|
||||
test_show_vec!(empty, "[]");
|
||||
|
@ -1083,7 +1074,7 @@ fn test_vec_default() {
|
|||
($ty:ty) => {{
|
||||
let v: $ty = Default::default();
|
||||
assert!(v.is_empty());
|
||||
}}
|
||||
}};
|
||||
}
|
||||
|
||||
t!(&[i32]);
|
||||
|
@ -1406,8 +1397,8 @@ fn test_box_slice_clone() {
|
|||
#[allow(unused_must_use)] // here, we care about the side effects of `.clone()`
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
fn test_box_slice_clone_panics() {
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
struct Canary {
|
||||
count: Arc<AtomicUsize>,
|
||||
|
@ -1426,32 +1417,23 @@ fn test_box_slice_clone_panics() {
|
|||
panic!()
|
||||
}
|
||||
|
||||
Canary {
|
||||
count: self.count.clone(),
|
||||
panics: self.panics,
|
||||
}
|
||||
Canary { count: self.count.clone(), panics: self.panics }
|
||||
}
|
||||
}
|
||||
|
||||
let drop_count = Arc::new(AtomicUsize::new(0));
|
||||
let canary = Canary {
|
||||
count: drop_count.clone(),
|
||||
panics: false,
|
||||
};
|
||||
let panic = Canary {
|
||||
count: drop_count.clone(),
|
||||
panics: true,
|
||||
};
|
||||
let canary = Canary { count: drop_count.clone(), panics: false };
|
||||
let panic = Canary { count: drop_count.clone(), panics: true };
|
||||
|
||||
std::panic::catch_unwind(move || {
|
||||
// When xs is dropped, +5.
|
||||
let xs = vec![canary.clone(), canary.clone(), canary.clone(), panic, canary]
|
||||
.into_boxed_slice();
|
||||
// When xs is dropped, +5.
|
||||
let xs =
|
||||
vec![canary.clone(), canary.clone(), canary.clone(), panic, canary].into_boxed_slice();
|
||||
|
||||
// When panic is cloned, +3.
|
||||
xs.clone();
|
||||
})
|
||||
.unwrap_err();
|
||||
// When panic is cloned, +3.
|
||||
xs.clone();
|
||||
})
|
||||
.unwrap_err();
|
||||
|
||||
// Total = 8
|
||||
assert_eq!(drop_count.load(Ordering::SeqCst), 8);
|
||||
|
@ -1485,26 +1467,86 @@ const MAX_LEN: usize = 80;
|
|||
|
||||
static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [
|
||||
// FIXME(RFC 1109): AtomicUsize is not Copy.
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
AtomicUsize::new(0),
|
||||
];
|
||||
|
||||
static VERSIONS: AtomicUsize = AtomicUsize::new(0);
|
||||
|
@ -1551,7 +1593,10 @@ macro_rules! test {
|
|||
// Work out the total number of comparisons required to sort
|
||||
// this array...
|
||||
let mut count = 0usize;
|
||||
$input.to_owned().$func(|a, b| { count += 1; a.cmp(b) });
|
||||
$input.to_owned().$func(|a, b| {
|
||||
count += 1;
|
||||
a.cmp(b)
|
||||
});
|
||||
|
||||
// ... and then panic on each and every single one.
|
||||
for panic_countdown in 0..count {
|
||||
|
@ -1579,15 +1624,13 @@ macro_rules! test {
|
|||
// what we expect (i.e., the contents of `v`).
|
||||
for (i, c) in DROP_COUNTS.iter().enumerate().take(len) {
|
||||
let count = c.load(Relaxed);
|
||||
assert!(count == 1,
|
||||
"found drop count == {} for i == {}, len == {}",
|
||||
count, i, len);
|
||||
assert!(count == 1, "found drop count == {} for i == {}, len == {}", count, i, len);
|
||||
}
|
||||
|
||||
// Check that the most recent versions of values were dropped.
|
||||
assert_eq!(VERSIONS.load(Relaxed), 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
thread_local!(static SILENCE_PANIC: Cell<bool> = Cell::new(false));
|
||||
|
@ -1618,12 +1661,10 @@ fn panic_safe() {
|
|||
for &modulus in moduli {
|
||||
for &has_runs in &[false, true] {
|
||||
let mut input = (0..len)
|
||||
.map(|id| {
|
||||
DropCounter {
|
||||
x: rng.next_u32() % modulus,
|
||||
id: id,
|
||||
version: Cell::new(0),
|
||||
}
|
||||
.map(|id| DropCounter {
|
||||
x: rng.next_u32() % modulus,
|
||||
id: id,
|
||||
version: Cell::new(0),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
@ -1658,8 +1699,5 @@ fn repeat_generic_slice() {
|
|||
assert_eq!([1, 2].repeat(2), vec![1, 2, 1, 2]);
|
||||
assert_eq!([1, 2, 3, 4].repeat(0), vec![]);
|
||||
assert_eq!([1, 2, 3, 4].repeat(1), vec![1, 2, 3, 4]);
|
||||
assert_eq!(
|
||||
[1, 2, 3, 4].repeat(3),
|
||||
vec![1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
|
||||
);
|
||||
assert_eq!([1, 2, 3, 4].repeat(3), vec![1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]);
|
||||
}
|
||||
|
|
|
@ -13,9 +13,9 @@ fn test_le() {
|
|||
#[test]
|
||||
fn test_find() {
|
||||
assert_eq!("hello".find('l'), Some(2));
|
||||
assert_eq!("hello".find(|c:char| c == 'o'), Some(4));
|
||||
assert_eq!("hello".find(|c: char| c == 'o'), Some(4));
|
||||
assert!("hello".find('x').is_none());
|
||||
assert!("hello".find(|c:char| c == 'x').is_none());
|
||||
assert!("hello".find(|c: char| c == 'x').is_none());
|
||||
assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30));
|
||||
assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30));
|
||||
}
|
||||
|
@ -23,9 +23,9 @@ fn test_find() {
|
|||
#[test]
|
||||
fn test_rfind() {
|
||||
assert_eq!("hello".rfind('l'), Some(3));
|
||||
assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4));
|
||||
assert_eq!("hello".rfind(|c: char| c == 'o'), Some(4));
|
||||
assert!("hello".rfind('x').is_none());
|
||||
assert!("hello".rfind(|c:char| c == 'x').is_none());
|
||||
assert!("hello".rfind(|c: char| c == 'x').is_none());
|
||||
assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30));
|
||||
assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30));
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ fn test_find_str() {
|
|||
assert_eq!(data[0..43].find(""), Some(0));
|
||||
assert_eq!(data[6..43].find(""), Some(6 - 6));
|
||||
|
||||
assert_eq!(data[0..43].find("ประ"), Some( 0));
|
||||
assert_eq!(data[0..43].find("ประ"), Some(0));
|
||||
assert_eq!(data[0..43].find("ทศไ"), Some(12));
|
||||
assert_eq!(data[0..43].find("ย中"), Some(24));
|
||||
assert_eq!(data[0..43].find("iệt"), Some(34));
|
||||
|
@ -81,10 +81,7 @@ fn test_find_str() {
|
|||
let string = "Việt Namacbaabcaabaaba";
|
||||
for (i, ci) in string.char_indices() {
|
||||
let ip = i + ci.len_utf8();
|
||||
for j in string[ip..].char_indices()
|
||||
.map(|(i, _)| i)
|
||||
.chain(Some(string.len() - ip))
|
||||
{
|
||||
for j in string[ip..].char_indices().map(|(i, _)| i).chain(Some(string.len() - ip)) {
|
||||
let pat = &string[i..ip + j];
|
||||
assert!(match string.find(pat) {
|
||||
None => false,
|
||||
|
@ -98,15 +95,15 @@ fn test_find_str() {
|
|||
}
|
||||
}
|
||||
|
||||
fn s(x: &str) -> String { x.to_string() }
|
||||
fn s(x: &str) -> String {
|
||||
x.to_string()
|
||||
}
|
||||
|
||||
macro_rules! test_concat {
|
||||
($expected: expr, $string: expr) => {
|
||||
{
|
||||
let s: String = $string.concat();
|
||||
assert_eq!($expected, s);
|
||||
}
|
||||
}
|
||||
($expected: expr, $string: expr) => {{
|
||||
let s: String = $string.concat();
|
||||
assert_eq!($expected, s);
|
||||
}};
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -125,12 +122,10 @@ fn test_concat_for_different_lengths() {
|
|||
}
|
||||
|
||||
macro_rules! test_join {
|
||||
($expected: expr, $string: expr, $delim: expr) => {
|
||||
{
|
||||
let s = $string.join($delim);
|
||||
assert_eq!($expected, s);
|
||||
}
|
||||
}
|
||||
($expected: expr, $string: expr, $delim: expr) => {{
|
||||
let s = $string.join($delim);
|
||||
assert_eq!($expected, s);
|
||||
}};
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -168,9 +163,9 @@ fn test_join_for_different_lengths_with_long_separator() {
|
|||
#[test]
|
||||
#[cfg_attr(miri, ignore)] // Miri is too slow
|
||||
fn test_unsafe_slice() {
|
||||
assert_eq!("ab", unsafe {"abc".get_unchecked(0..2)});
|
||||
assert_eq!("bc", unsafe {"abc".get_unchecked(1..3)});
|
||||
assert_eq!("", unsafe {"abc".get_unchecked(1..1)});
|
||||
assert_eq!("ab", unsafe { "abc".get_unchecked(0..2) });
|
||||
assert_eq!("bc", unsafe { "abc".get_unchecked(1..3) });
|
||||
assert_eq!("", unsafe { "abc".get_unchecked(1..1) });
|
||||
fn a_million_letter_a() -> String {
|
||||
let mut i = 0;
|
||||
let mut rs = String::new();
|
||||
|
@ -190,8 +185,7 @@ fn test_unsafe_slice() {
|
|||
rs
|
||||
}
|
||||
let letters = a_million_letter_a();
|
||||
assert_eq!(half_a_million_letter_a(),
|
||||
unsafe { letters.get_unchecked(0..500000)});
|
||||
assert_eq!(half_a_million_letter_a(), unsafe { letters.get_unchecked(0..500000) });
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -304,8 +298,7 @@ mod slice_index {
|
|||
//
|
||||
// This is not suitable for testing failure on invalid inputs.
|
||||
macro_rules! assert_range_eq {
|
||||
($s:expr, $range:expr, $expected:expr)
|
||||
=> {
|
||||
($s:expr, $range:expr, $expected:expr) => {
|
||||
let mut s: String = $s.to_owned();
|
||||
let mut expected: String = $expected.to_owned();
|
||||
{
|
||||
|
@ -316,7 +309,8 @@ mod slice_index {
|
|||
assert_eq!(s.get($range), Some(expected), "(in assertion for: get)");
|
||||
unsafe {
|
||||
assert_eq!(
|
||||
s.get_unchecked($range), expected,
|
||||
s.get_unchecked($range),
|
||||
expected,
|
||||
"(in assertion for: get_unchecked)",
|
||||
);
|
||||
}
|
||||
|
@ -325,22 +319,21 @@ mod slice_index {
|
|||
let s: &mut str = &mut s;
|
||||
let expected: &mut str = &mut expected;
|
||||
|
||||
assert_eq!(&mut s[$range], expected, "(in assertion for: index_mut)",);
|
||||
assert_eq!(
|
||||
&mut s[$range], expected,
|
||||
"(in assertion for: index_mut)",
|
||||
);
|
||||
assert_eq!(
|
||||
s.get_mut($range), Some(&mut expected[..]),
|
||||
s.get_mut($range),
|
||||
Some(&mut expected[..]),
|
||||
"(in assertion for: get_mut)",
|
||||
);
|
||||
unsafe {
|
||||
assert_eq!(
|
||||
s.get_unchecked_mut($range), expected,
|
||||
s.get_unchecked_mut($range),
|
||||
expected,
|
||||
"(in assertion for: get_unchecked_mut)",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Make sure the macro can actually detect bugs,
|
||||
|
@ -460,15 +453,15 @@ mod slice_index {
|
|||
assert_range_eq!(data, 30..33, "华");
|
||||
|
||||
/*0: 中
|
||||
3: 华
|
||||
6: V
|
||||
7: i
|
||||
8: ệ
|
||||
11: t
|
||||
12:
|
||||
13: N
|
||||
14: a
|
||||
15: m */
|
||||
3: 华
|
||||
6: V
|
||||
7: i
|
||||
8: ệ
|
||||
11: t
|
||||
12:
|
||||
13: N
|
||||
14: a
|
||||
15: m */
|
||||
let ss = "中华Việt Nam";
|
||||
assert_range_eq!(ss, 3..6, "华");
|
||||
assert_range_eq!(ss, 6..16, "Việt Nam");
|
||||
|
@ -660,13 +653,13 @@ mod slice_index {
|
|||
|
||||
// check the panic includes the prefix of the sliced string
|
||||
#[test]
|
||||
#[should_panic(expected="byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
|
||||
#[should_panic(expected = "byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
|
||||
fn test_slice_fail_truncated_1() {
|
||||
&LOREM_PARAGRAPH[..1024];
|
||||
}
|
||||
// check the truncation in the panic message
|
||||
#[test]
|
||||
#[should_panic(expected="luctus, im`[...]")]
|
||||
#[should_panic(expected = "luctus, im`[...]")]
|
||||
fn test_slice_fail_truncated_2() {
|
||||
&LOREM_PARAGRAPH[..1024];
|
||||
}
|
||||
|
@ -712,8 +705,12 @@ fn test_is_char_boundary() {
|
|||
// ensure character locations are boundaries and continuation bytes are not
|
||||
assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
|
||||
for j in 1..ch.len_utf8() {
|
||||
assert!(!s.is_char_boundary(i + j),
|
||||
"{} should not be a char boundary in {:?}", i + j, s);
|
||||
assert!(
|
||||
!s.is_char_boundary(i + j),
|
||||
"{} should not be a char boundary in {:?}",
|
||||
i + j,
|
||||
s
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -846,7 +843,7 @@ fn from_utf8_error() {
|
|||
let error = from_utf8($input).unwrap_err();
|
||||
assert_eq!(error.valid_up_to(), $expected_valid_up_to);
|
||||
assert_eq!(error.error_len(), $expected_error_len);
|
||||
}
|
||||
};
|
||||
}
|
||||
test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
|
||||
test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
|
||||
|
@ -873,9 +870,8 @@ fn from_utf8_error() {
|
|||
fn test_as_bytes() {
|
||||
// no null
|
||||
let v = [
|
||||
224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
|
||||
184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
|
||||
109
|
||||
224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
|
||||
86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
|
||||
];
|
||||
let b: &[u8] = &[];
|
||||
assert_eq!("".as_bytes(), b);
|
||||
|
@ -1010,8 +1006,10 @@ fn test_escape_debug() {
|
|||
assert_eq!("\u{10000}\u{10ffff}".escape_debug().to_string(), "\u{10000}\\u{10ffff}");
|
||||
assert_eq!("ab\u{200b}".escape_debug().to_string(), "ab\\u{200b}");
|
||||
assert_eq!("\u{10d4ea}\r".escape_debug().to_string(), "\\u{10d4ea}\\r");
|
||||
assert_eq!("\u{301}a\u{301}bé\u{e000}".escape_debug().to_string(),
|
||||
"\\u{301}a\u{301}bé\\u{e000}");
|
||||
assert_eq!(
|
||||
"\u{301}a\u{301}bé\u{e000}".escape_debug().to_string(),
|
||||
"\\u{301}a\u{301}bé\\u{e000}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1040,7 +1038,7 @@ fn test_total_ord() {
|
|||
#[test]
|
||||
fn test_iterator() {
|
||||
let s = "ศไทย中华Việt Nam";
|
||||
let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
|
||||
let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'];
|
||||
|
||||
let mut pos = 0;
|
||||
let it = s.chars();
|
||||
|
@ -1056,7 +1054,7 @@ fn test_iterator() {
|
|||
#[test]
|
||||
fn test_rev_iterator() {
|
||||
let s = "ศไทย中华Việt Nam";
|
||||
let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
|
||||
let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ'];
|
||||
|
||||
let mut pos = 0;
|
||||
let it = s.chars().rev();
|
||||
|
@ -1097,7 +1095,7 @@ fn test_iterator_clone() {
|
|||
let s = "ศไทย中华Việt Nam";
|
||||
let mut it = s.chars();
|
||||
it.next();
|
||||
assert!(it.clone().zip(it).all(|(x,y)| x == y));
|
||||
assert!(it.clone().zip(it).all(|(x, y)| x == y));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1122,9 +1120,8 @@ fn test_chars_debug() {
|
|||
fn test_bytesator() {
|
||||
let s = "ศไทย中华Việt Nam";
|
||||
let v = [
|
||||
224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
|
||||
184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
|
||||
109
|
||||
224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
|
||||
86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
|
||||
];
|
||||
let mut pos = 0;
|
||||
|
||||
|
@ -1138,9 +1135,8 @@ fn test_bytesator() {
|
|||
fn test_bytes_revator() {
|
||||
let s = "ศไทย中华Việt Nam";
|
||||
let v = [
|
||||
224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
|
||||
184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
|
||||
109
|
||||
224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
|
||||
86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
|
||||
];
|
||||
let mut pos = v.len();
|
||||
|
||||
|
@ -1154,9 +1150,8 @@ fn test_bytes_revator() {
|
|||
fn test_bytesator_nth() {
|
||||
let s = "ศไทย中华Việt Nam";
|
||||
let v = [
|
||||
224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
|
||||
184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
|
||||
109
|
||||
224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
|
||||
86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
|
||||
];
|
||||
|
||||
let mut b = s.bytes();
|
||||
|
@ -1185,7 +1180,7 @@ fn test_bytesator_last() {
|
|||
fn test_char_indicesator() {
|
||||
let s = "ศไทย中华Việt Nam";
|
||||
let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
|
||||
let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
|
||||
let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'];
|
||||
|
||||
let mut pos = 0;
|
||||
let it = s.char_indices();
|
||||
|
@ -1202,7 +1197,7 @@ fn test_char_indicesator() {
|
|||
fn test_char_indices_revator() {
|
||||
let s = "ศไทย中华Việt Nam";
|
||||
let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
|
||||
let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
|
||||
let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ'];
|
||||
|
||||
let mut pos = 0;
|
||||
let it = s.char_indices().rev();
|
||||
|
@ -1314,10 +1309,10 @@ fn test_splitator() {
|
|||
t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
|
||||
t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
|
||||
t("", ".", &[""]);
|
||||
t("zz", "zz", &["",""]);
|
||||
t("zz", "zz", &["", ""]);
|
||||
t("ok", "z", &["ok"]);
|
||||
t("zzz", "zz", &["","z"]);
|
||||
t("zzzzz", "zz", &["","","z"]);
|
||||
t("zzz", "zz", &["", "z"]);
|
||||
t("zzzzz", "zz", &["", "", "z"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1383,7 +1378,7 @@ fn test_bool_from_str() {
|
|||
fn check_contains_all_substrings(s: &str) {
|
||||
assert!(s.contains(""));
|
||||
for i in 0..s.len() {
|
||||
for j in i+1..=s.len() {
|
||||
for j in i + 1..=s.len() {
|
||||
assert!(s.contains(&s[i..j]));
|
||||
}
|
||||
}
|
||||
|
@ -1405,7 +1400,6 @@ fn strslice_issue_16878() {
|
|||
assert!(!"00abc01234567890123456789abc".contains("bcabc"));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore)] // Miri is too slow
|
||||
fn test_strslice_contains() {
|
||||
|
@ -1440,14 +1434,14 @@ fn test_split_char_iterator() {
|
|||
let data = "\nMäry häd ä little lämb\nLittle lämb\n";
|
||||
|
||||
let split: Vec<&str> = data.split(' ').collect();
|
||||
assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
|
||||
let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
|
||||
rsplit.reverse();
|
||||
assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
|
||||
let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
|
||||
assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
|
||||
let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
|
||||
rsplit.reverse();
|
||||
|
@ -1455,14 +1449,14 @@ fn test_split_char_iterator() {
|
|||
|
||||
// Unicode
|
||||
let split: Vec<&str> = data.split('ä').collect();
|
||||
assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
|
||||
let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
|
||||
rsplit.reverse();
|
||||
assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
|
||||
let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
|
||||
assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
|
||||
let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
|
||||
rsplit.reverse();
|
||||
|
@ -1484,8 +1478,7 @@ fn test_rev_split_char_iterator_no_trailing() {
|
|||
|
||||
#[test]
|
||||
fn test_utf16_code_units() {
|
||||
assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(),
|
||||
[0xE9, 0xD83D, 0xDCA9])
|
||||
assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(), [0xE9, 0xD83D, 0xDCA9])
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1521,26 +1514,16 @@ fn contains_weird_cases() {
|
|||
|
||||
#[test]
|
||||
fn trim_ws() {
|
||||
assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()),
|
||||
"a \t ");
|
||||
assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()),
|
||||
" \t a");
|
||||
assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()),
|
||||
"a \t ");
|
||||
assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()),
|
||||
" \t a");
|
||||
assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()),
|
||||
"a");
|
||||
assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()),
|
||||
"");
|
||||
assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()),
|
||||
"");
|
||||
assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()),
|
||||
"");
|
||||
assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()),
|
||||
"");
|
||||
assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()),
|
||||
"");
|
||||
assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t ");
|
||||
assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a");
|
||||
assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t ");
|
||||
assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a");
|
||||
assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()), "a");
|
||||
assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), "");
|
||||
assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), "");
|
||||
assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), "");
|
||||
assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), "");
|
||||
assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1616,8 +1599,8 @@ fn test_repeat() {
|
|||
}
|
||||
|
||||
mod pattern {
|
||||
use std::str::pattern::{Pattern, Searcher, ReverseSearcher};
|
||||
use std::str::pattern::SearchStep::{self, Match, Reject, Done};
|
||||
use std::str::pattern::SearchStep::{self, Done, Match, Reject};
|
||||
use std::str::pattern::{Pattern, ReverseSearcher, Searcher};
|
||||
|
||||
macro_rules! make_test {
|
||||
($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
|
||||
|
@ -1641,12 +1624,12 @@ mod pattern {
|
|||
rev: bool,
|
||||
pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>,
|
||||
haystack: &'a str,
|
||||
right: Vec<SearchStep>
|
||||
right: Vec<SearchStep>,
|
||||
) {
|
||||
let mut searcher = pat.into_searcher(haystack);
|
||||
let mut v = vec![];
|
||||
loop {
|
||||
match if !rev {searcher.next()} else {searcher.next_back()} {
|
||||
match if !rev { searcher.next() } else { searcher.next_back() } {
|
||||
Match(a, b) => v.push(Match(a, b)),
|
||||
Reject(a, b) => v.push(Reject(a, b)),
|
||||
Done => break,
|
||||
|
@ -1661,8 +1644,7 @@ mod pattern {
|
|||
|
||||
for (i, e) in right.iter().enumerate() {
|
||||
match *e {
|
||||
Match(a, b) | Reject(a, b)
|
||||
if a <= b && a == first_index => {
|
||||
Match(a, b) | Reject(a, b) if a <= b && a == first_index => {
|
||||
first_index = b;
|
||||
}
|
||||
_ => {
|
||||
|
@ -1683,77 +1665,88 @@ mod pattern {
|
|||
assert_eq!(v, right);
|
||||
}
|
||||
|
||||
make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
|
||||
Reject(0, 1),
|
||||
Match (1, 3),
|
||||
Reject(3, 4),
|
||||
Match (4, 6),
|
||||
Reject(6, 7),
|
||||
]);
|
||||
make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
|
||||
Reject(0, 1),
|
||||
Match (1, 3),
|
||||
Reject(3, 4),
|
||||
Match (4, 6),
|
||||
Match (6, 8),
|
||||
Reject(8, 9),
|
||||
]);
|
||||
make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
|
||||
Match (0, 0),
|
||||
Reject(0, 1),
|
||||
Match (1, 1),
|
||||
Reject(1, 2),
|
||||
Match (2, 2),
|
||||
Reject(2, 3),
|
||||
Match (3, 3),
|
||||
Reject(3, 4),
|
||||
Match (4, 4),
|
||||
Reject(4, 5),
|
||||
Match (5, 5),
|
||||
Reject(5, 6),
|
||||
Match (6, 6),
|
||||
Reject(6, 7),
|
||||
Match (7, 7),
|
||||
]);
|
||||
make_test!(str_searcher_multibyte_haystack, " ", "├──", [
|
||||
Reject(0, 3),
|
||||
Reject(3, 6),
|
||||
Reject(6, 9),
|
||||
]);
|
||||
make_test!(str_searcher_empty_needle_multibyte_haystack, "", "├──", [
|
||||
Match (0, 0),
|
||||
Reject(0, 3),
|
||||
Match (3, 3),
|
||||
Reject(3, 6),
|
||||
Match (6, 6),
|
||||
Reject(6, 9),
|
||||
Match (9, 9),
|
||||
]);
|
||||
make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
|
||||
Match(0, 0),
|
||||
]);
|
||||
make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
|
||||
]);
|
||||
make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
|
||||
Reject(0, 1),
|
||||
Match (1, 2),
|
||||
Match (2, 3),
|
||||
Reject(3, 4),
|
||||
Match (4, 5),
|
||||
Match (5, 6),
|
||||
Reject(6, 7),
|
||||
]);
|
||||
make_test!(char_searcher_multibyte_haystack, ' ', "├──", [
|
||||
Reject(0, 3),
|
||||
Reject(3, 6),
|
||||
Reject(6, 9),
|
||||
]);
|
||||
make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
|
||||
Reject(0, 1),
|
||||
Reject(1, 2),
|
||||
Reject(2, 3),
|
||||
]);
|
||||
|
||||
make_test!(
|
||||
str_searcher_ascii_haystack,
|
||||
"bb",
|
||||
"abbcbbd",
|
||||
[Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Reject(6, 7),]
|
||||
);
|
||||
make_test!(
|
||||
str_searcher_ascii_haystack_seq,
|
||||
"bb",
|
||||
"abbcbbbbd",
|
||||
[Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Match(6, 8), Reject(8, 9),]
|
||||
);
|
||||
make_test!(
|
||||
str_searcher_empty_needle_ascii_haystack,
|
||||
"",
|
||||
"abbcbbd",
|
||||
[
|
||||
Match(0, 0),
|
||||
Reject(0, 1),
|
||||
Match(1, 1),
|
||||
Reject(1, 2),
|
||||
Match(2, 2),
|
||||
Reject(2, 3),
|
||||
Match(3, 3),
|
||||
Reject(3, 4),
|
||||
Match(4, 4),
|
||||
Reject(4, 5),
|
||||
Match(5, 5),
|
||||
Reject(5, 6),
|
||||
Match(6, 6),
|
||||
Reject(6, 7),
|
||||
Match(7, 7),
|
||||
]
|
||||
);
|
||||
make_test!(
|
||||
str_searcher_multibyte_haystack,
|
||||
" ",
|
||||
"├──",
|
||||
[Reject(0, 3), Reject(3, 6), Reject(6, 9),]
|
||||
);
|
||||
make_test!(
|
||||
str_searcher_empty_needle_multibyte_haystack,
|
||||
"",
|
||||
"├──",
|
||||
[
|
||||
Match(0, 0),
|
||||
Reject(0, 3),
|
||||
Match(3, 3),
|
||||
Reject(3, 6),
|
||||
Match(6, 6),
|
||||
Reject(6, 9),
|
||||
Match(9, 9),
|
||||
]
|
||||
);
|
||||
make_test!(str_searcher_empty_needle_empty_haystack, "", "", [Match(0, 0),]);
|
||||
make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", []);
|
||||
make_test!(
|
||||
char_searcher_ascii_haystack,
|
||||
'b',
|
||||
"abbcbbd",
|
||||
[
|
||||
Reject(0, 1),
|
||||
Match(1, 2),
|
||||
Match(2, 3),
|
||||
Reject(3, 4),
|
||||
Match(4, 5),
|
||||
Match(5, 6),
|
||||
Reject(6, 7),
|
||||
]
|
||||
);
|
||||
make_test!(
|
||||
char_searcher_multibyte_haystack,
|
||||
' ',
|
||||
"├──",
|
||||
[Reject(0, 3), Reject(3, 6), Reject(6, 9),]
|
||||
);
|
||||
make_test!(
|
||||
char_searcher_short_haystack,
|
||||
'\u{1F4A9}',
|
||||
"* \t",
|
||||
[Reject(0, 1), Reject(1, 2), Reject(2, 3),]
|
||||
);
|
||||
}
|
||||
|
||||
macro_rules! generate_iterator_test {
|
||||
|
@ -1850,7 +1843,10 @@ generate_iterator_test! {
|
|||
fn different_str_pattern_forwarding_lifetimes() {
|
||||
use std::str::pattern::Pattern;
|
||||
|
||||
fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {
|
||||
fn foo<'a, P>(p: P)
|
||||
where
|
||||
for<'b> &'b P: Pattern<'a>,
|
||||
{
|
||||
for _ in 0..3 {
|
||||
"asdf".find(&p);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
use std::borrow::Cow;
|
||||
use std::collections::TryReserveError::*;
|
||||
use std::mem::size_of;
|
||||
use std::{usize, isize};
|
||||
use std::{isize, usize};
|
||||
|
||||
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
|
||||
pub trait IntoCow<'a, B: ?Sized>
|
||||
where
|
||||
B: ToOwned,
|
||||
{
|
||||
fn into_cow(self) -> Cow<'a, B>;
|
||||
}
|
||||
|
||||
|
@ -43,8 +46,7 @@ fn test_from_utf8() {
|
|||
assert_eq!(String::from_utf8(xs).unwrap(), String::from("hello"));
|
||||
|
||||
let xs = "ศไทย中华Việt Nam".as_bytes().to_vec();
|
||||
assert_eq!(String::from_utf8(xs).unwrap(),
|
||||
String::from("ศไทย中华Việt Nam"));
|
||||
assert_eq!(String::from_utf8(xs).unwrap(), String::from("ศไทย中华Việt Nam"));
|
||||
|
||||
let xs = b"hello\xFF".to_vec();
|
||||
let err = String::from_utf8(xs).unwrap_err();
|
||||
|
@ -62,60 +64,87 @@ fn test_from_utf8_lossy() {
|
|||
assert_eq!(String::from_utf8_lossy(xs), ys);
|
||||
|
||||
let xs = b"Hello\xC2 There\xFF Goodbye";
|
||||
assert_eq!(String::from_utf8_lossy(xs),
|
||||
String::from("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow());
|
||||
assert_eq!(
|
||||
String::from_utf8_lossy(xs),
|
||||
String::from("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow()
|
||||
);
|
||||
|
||||
let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
|
||||
assert_eq!(String::from_utf8_lossy(xs),
|
||||
String::from("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow());
|
||||
assert_eq!(
|
||||
String::from_utf8_lossy(xs),
|
||||
String::from("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow()
|
||||
);
|
||||
|
||||
let xs = b"\xF5foo\xF5\x80bar";
|
||||
assert_eq!(String::from_utf8_lossy(xs),
|
||||
String::from("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow());
|
||||
assert_eq!(
|
||||
String::from_utf8_lossy(xs),
|
||||
String::from("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow()
|
||||
);
|
||||
|
||||
let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz";
|
||||
assert_eq!(String::from_utf8_lossy(xs),
|
||||
String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow());
|
||||
assert_eq!(
|
||||
String::from_utf8_lossy(xs),
|
||||
String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow()
|
||||
);
|
||||
|
||||
let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz";
|
||||
assert_eq!(String::from_utf8_lossy(xs),
|
||||
String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow());
|
||||
assert_eq!(
|
||||
String::from_utf8_lossy(xs),
|
||||
String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow()
|
||||
);
|
||||
|
||||
let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar";
|
||||
assert_eq!(String::from_utf8_lossy(xs),
|
||||
String::from("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}foo\u{10000}bar").into_cow());
|
||||
assert_eq!(
|
||||
String::from_utf8_lossy(xs),
|
||||
String::from("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}foo\u{10000}bar").into_cow()
|
||||
);
|
||||
|
||||
// surrogates
|
||||
let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar";
|
||||
assert_eq!(String::from_utf8_lossy(xs),
|
||||
String::from("\u{FFFD}\u{FFFD}\u{FFFD}foo\u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow());
|
||||
assert_eq!(
|
||||
String::from_utf8_lossy(xs),
|
||||
String::from("\u{FFFD}\u{FFFD}\u{FFFD}foo\u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_utf16() {
|
||||
let pairs = [(String::from("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"),
|
||||
vec![0xd800, 0xdf45, 0xd800, 0xdf3f, 0xd800, 0xdf3b, 0xd800, 0xdf46, 0xd800,
|
||||
0xdf39, 0xd800, 0xdf3b, 0xd800, 0xdf30, 0x000a]),
|
||||
|
||||
(String::from("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"),
|
||||
vec![0xd801, 0xdc12, 0xd801, 0xdc49, 0xd801, 0xdc2e, 0xd801, 0xdc40, 0xd801,
|
||||
0xdc32, 0xd801, 0xdc4b, 0x0020, 0xd801, 0xdc0f, 0xd801, 0xdc32, 0xd801,
|
||||
0xdc4d, 0x000a]),
|
||||
|
||||
(String::from("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"),
|
||||
vec![0xd800, 0xdf00, 0xd800, 0xdf16, 0xd800, 0xdf0b, 0xd800, 0xdf04, 0xd800,
|
||||
0xdf11, 0xd800, 0xdf09, 0x00b7, 0xd800, 0xdf0c, 0xd800, 0xdf04, 0xd800,
|
||||
0xdf15, 0xd800, 0xdf04, 0xd800, 0xdf0b, 0xd800, 0xdf09, 0xd800, 0xdf11,
|
||||
0x000a]),
|
||||
|
||||
(String::from("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"),
|
||||
vec![0xd801, 0xdc8b, 0xd801, 0xdc98, 0xd801, 0xdc88, 0xd801, 0xdc91, 0xd801,
|
||||
0xdc9b, 0xd801, 0xdc92, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc93, 0x0020,
|
||||
0xd801, 0xdc88, 0xd801, 0xdc9a, 0xd801, 0xdc8d, 0x0020, 0xd801, 0xdc8f,
|
||||
0xd801, 0xdc9c, 0xd801, 0xdc92, 0xd801, 0xdc96, 0xd801, 0xdc86, 0x0020,
|
||||
0xd801, 0xdc95, 0xd801, 0xdc86, 0x000a]),
|
||||
// Issue #12318, even-numbered non-BMP planes
|
||||
(String::from("\u{20000}"), vec![0xD840, 0xDC00])];
|
||||
let pairs = [
|
||||
(
|
||||
String::from("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"),
|
||||
vec![
|
||||
0xd800, 0xdf45, 0xd800, 0xdf3f, 0xd800, 0xdf3b, 0xd800, 0xdf46, 0xd800, 0xdf39,
|
||||
0xd800, 0xdf3b, 0xd800, 0xdf30, 0x000a,
|
||||
],
|
||||
),
|
||||
(
|
||||
String::from("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"),
|
||||
vec![
|
||||
0xd801, 0xdc12, 0xd801, 0xdc49, 0xd801, 0xdc2e, 0xd801, 0xdc40, 0xd801, 0xdc32,
|
||||
0xd801, 0xdc4b, 0x0020, 0xd801, 0xdc0f, 0xd801, 0xdc32, 0xd801, 0xdc4d, 0x000a,
|
||||
],
|
||||
),
|
||||
(
|
||||
String::from("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"),
|
||||
vec![
|
||||
0xd800, 0xdf00, 0xd800, 0xdf16, 0xd800, 0xdf0b, 0xd800, 0xdf04, 0xd800, 0xdf11,
|
||||
0xd800, 0xdf09, 0x00b7, 0xd800, 0xdf0c, 0xd800, 0xdf04, 0xd800, 0xdf15, 0xd800,
|
||||
0xdf04, 0xd800, 0xdf0b, 0xd800, 0xdf09, 0xd800, 0xdf11, 0x000a,
|
||||
],
|
||||
),
|
||||
(
|
||||
String::from("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"),
|
||||
vec![
|
||||
0xd801, 0xdc8b, 0xd801, 0xdc98, 0xd801, 0xdc88, 0xd801, 0xdc91, 0xd801, 0xdc9b,
|
||||
0xd801, 0xdc92, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc93, 0x0020, 0xd801, 0xdc88,
|
||||
0xd801, 0xdc9a, 0xd801, 0xdc8d, 0x0020, 0xd801, 0xdc8f, 0xd801, 0xdc9c, 0xd801,
|
||||
0xdc92, 0xd801, 0xdc96, 0xd801, 0xdc86, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc86,
|
||||
0x000a,
|
||||
],
|
||||
),
|
||||
// Issue #12318, even-numbered non-BMP planes
|
||||
(String::from("\u{20000}"), vec![0xD840, 0xDC00]),
|
||||
];
|
||||
|
||||
for p in &pairs {
|
||||
let (s, u) = (*p).clone();
|
||||
|
@ -152,19 +181,18 @@ fn test_utf16_invalid() {
|
|||
fn test_from_utf16_lossy() {
|
||||
// completely positive cases tested above.
|
||||
// lead + eof
|
||||
assert_eq!(String::from_utf16_lossy(&[0xD800]),
|
||||
String::from("\u{FFFD}"));
|
||||
assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from("\u{FFFD}"));
|
||||
// lead + lead
|
||||
assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]),
|
||||
String::from("\u{FFFD}\u{FFFD}"));
|
||||
assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]), String::from("\u{FFFD}\u{FFFD}"));
|
||||
|
||||
// isolated trail
|
||||
assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]),
|
||||
String::from("a\u{FFFD}"));
|
||||
assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from("a\u{FFFD}"));
|
||||
|
||||
// general
|
||||
assert_eq!(String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]),
|
||||
String::from("\u{FFFD}𐒋\u{FFFD}"));
|
||||
assert_eq!(
|
||||
String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]),
|
||||
String::from("\u{FFFD}𐒋\u{FFFD}")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -525,7 +553,6 @@ fn test_reserve_exact() {
|
|||
#[test]
|
||||
#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
|
||||
fn test_try_reserve() {
|
||||
|
||||
// These are the interesting cases:
|
||||
// * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM)
|
||||
// * > isize::MAX should always fail
|
||||
|
@ -559,23 +586,30 @@ fn test_try_reserve() {
|
|||
if guards_against_isize {
|
||||
// Check isize::MAX + 1 does count as overflow
|
||||
if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP + 1) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an overflow!") }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an overflow!")
|
||||
}
|
||||
|
||||
// Check usize::MAX does count as overflow
|
||||
if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_USIZE) {
|
||||
} else { panic!("usize::MAX should trigger an overflow!") }
|
||||
} else {
|
||||
panic!("usize::MAX should trigger an overflow!")
|
||||
}
|
||||
} else {
|
||||
// Check isize::MAX + 1 is an OOM
|
||||
if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_CAP + 1) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an OOM!")
|
||||
}
|
||||
|
||||
// Check usize::MAX is an OOM
|
||||
if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_USIZE) {
|
||||
} else { panic!("usize::MAX should trigger an OOM!") }
|
||||
} else {
|
||||
panic!("usize::MAX should trigger an OOM!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
// Same basic idea, but with non-zero len
|
||||
let mut ten_bytes: String = String::from("0123456789");
|
||||
|
@ -588,22 +622,26 @@ fn test_try_reserve() {
|
|||
}
|
||||
if guards_against_isize {
|
||||
if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an overflow!"); }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an overflow!");
|
||||
}
|
||||
} else {
|
||||
if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an OOM!")
|
||||
}
|
||||
}
|
||||
// Should always overflow in the add-to-len
|
||||
if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) {
|
||||
} else { panic!("usize::MAX should trigger an overflow!") }
|
||||
} else {
|
||||
panic!("usize::MAX should trigger an overflow!")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
|
||||
fn test_try_reserve_exact() {
|
||||
|
||||
// This is exactly the same as test_try_reserve with the method changed.
|
||||
// See that test for comments.
|
||||
|
||||
|
@ -624,20 +662,27 @@ fn test_try_reserve_exact() {
|
|||
|
||||
if guards_against_isize {
|
||||
if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP + 1) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an overflow!") }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an overflow!")
|
||||
}
|
||||
|
||||
if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_USIZE) {
|
||||
} else { panic!("usize::MAX should trigger an overflow!") }
|
||||
} else {
|
||||
panic!("usize::MAX should trigger an overflow!")
|
||||
}
|
||||
} else {
|
||||
if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_CAP + 1) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an OOM!")
|
||||
}
|
||||
|
||||
if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_USIZE) {
|
||||
} else { panic!("usize::MAX should trigger an OOM!") }
|
||||
} else {
|
||||
panic!("usize::MAX should trigger an OOM!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
let mut ten_bytes: String = String::from("0123456789");
|
||||
|
||||
|
@ -649,13 +694,18 @@ fn test_try_reserve_exact() {
|
|||
}
|
||||
if guards_against_isize {
|
||||
if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an overflow!"); }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an overflow!");
|
||||
}
|
||||
} else {
|
||||
if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an OOM!")
|
||||
}
|
||||
}
|
||||
if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
|
||||
} else { panic!("usize::MAX should trigger an overflow!") }
|
||||
} else {
|
||||
panic!("usize::MAX should trigger an overflow!")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use std::borrow::Cow;
|
||||
use std::mem::size_of;
|
||||
use std::{usize, isize};
|
||||
use std::vec::{Drain, IntoIter};
|
||||
use std::collections::TryReserveError::*;
|
||||
use std::mem::size_of;
|
||||
use std::vec::{Drain, IntoIter};
|
||||
use std::{isize, usize};
|
||||
|
||||
struct DropCounter<'a> {
|
||||
count: &'a mut u32,
|
||||
|
@ -28,10 +28,7 @@ fn test_double_drop() {
|
|||
|
||||
let (mut count_x, mut count_y) = (0, 0);
|
||||
{
|
||||
let mut tv = TwoVec {
|
||||
x: Vec::new(),
|
||||
y: Vec::new(),
|
||||
};
|
||||
let mut tv = TwoVec { x: Vec::new(), y: Vec::new() };
|
||||
tv.x.push(DropCounter { count: &mut count_x });
|
||||
tv.y.push(DropCounter { count: &mut count_y });
|
||||
|
||||
|
@ -271,7 +268,12 @@ fn test_dedup_by() {
|
|||
assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
|
||||
|
||||
let mut vec = vec![("foo", 1), ("foo", 2), ("bar", 3), ("bar", 4), ("bar", 5)];
|
||||
vec.dedup_by(|a, b| a.0 == b.0 && { b.1 += a.1; true });
|
||||
vec.dedup_by(|a, b| {
|
||||
a.0 == b.0 && {
|
||||
b.1 += a.1;
|
||||
true
|
||||
}
|
||||
});
|
||||
|
||||
assert_eq!(vec, [("foo", 3), ("bar", 12)]);
|
||||
}
|
||||
|
@ -323,14 +325,10 @@ fn zero_sized_values() {
|
|||
|
||||
#[test]
|
||||
fn test_partition() {
|
||||
assert_eq!(vec![].into_iter().partition(|x: &i32| *x < 3),
|
||||
(vec![], vec![]));
|
||||
assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 4),
|
||||
(vec![1, 2, 3], vec![]));
|
||||
assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 2),
|
||||
(vec![1], vec![2, 3]));
|
||||
assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 0),
|
||||
(vec![], vec![1, 2, 3]));
|
||||
assert_eq!(vec![].into_iter().partition(|x: &i32| *x < 3), (vec![], vec![]));
|
||||
assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 4), (vec![1, 2, 3], vec![]));
|
||||
assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 2), (vec![1], vec![2, 3]));
|
||||
assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 0), (vec![], vec![1, 2, 3]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -509,66 +507,59 @@ fn test_drain_out_of_bounds() {
|
|||
#[test]
|
||||
fn test_drain_range() {
|
||||
let mut v = vec![1, 2, 3, 4, 5];
|
||||
for _ in v.drain(4..) {
|
||||
}
|
||||
for _ in v.drain(4..) {}
|
||||
assert_eq!(v, &[1, 2, 3, 4]);
|
||||
|
||||
let mut v: Vec<_> = (1..6).map(|x| x.to_string()).collect();
|
||||
for _ in v.drain(1..4) {
|
||||
}
|
||||
for _ in v.drain(1..4) {}
|
||||
assert_eq!(v, &[1.to_string(), 5.to_string()]);
|
||||
|
||||
let mut v: Vec<_> = (1..6).map(|x| x.to_string()).collect();
|
||||
for _ in v.drain(1..4).rev() {
|
||||
}
|
||||
for _ in v.drain(1..4).rev() {}
|
||||
assert_eq!(v, &[1.to_string(), 5.to_string()]);
|
||||
|
||||
let mut v: Vec<_> = vec![(); 5];
|
||||
for _ in v.drain(1..4).rev() {
|
||||
}
|
||||
for _ in v.drain(1..4).rev() {}
|
||||
assert_eq!(v, &[(), ()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_drain_inclusive_range() {
|
||||
let mut v = vec!['a', 'b', 'c', 'd', 'e'];
|
||||
for _ in v.drain(1..=3) {
|
||||
}
|
||||
for _ in v.drain(1..=3) {}
|
||||
assert_eq!(v, &['a', 'e']);
|
||||
|
||||
let mut v: Vec<_> = (0..=5).map(|x| x.to_string()).collect();
|
||||
for _ in v.drain(1..=5) {
|
||||
}
|
||||
for _ in v.drain(1..=5) {}
|
||||
assert_eq!(v, &["0".to_string()]);
|
||||
|
||||
let mut v: Vec<String> = (0..=5).map(|x| x.to_string()).collect();
|
||||
for _ in v.drain(0..=5) {
|
||||
}
|
||||
for _ in v.drain(0..=5) {}
|
||||
assert_eq!(v, Vec::<String>::new());
|
||||
|
||||
let mut v: Vec<_> = (0..=5).map(|x| x.to_string()).collect();
|
||||
for _ in v.drain(0..=3) {
|
||||
}
|
||||
for _ in v.drain(0..=3) {}
|
||||
assert_eq!(v, &["4".to_string(), "5".to_string()]);
|
||||
|
||||
let mut v: Vec<_> = (0..=1).map(|x| x.to_string()).collect();
|
||||
for _ in v.drain(..=0) {
|
||||
}
|
||||
for _ in v.drain(..=0) {}
|
||||
assert_eq!(v, &["1".to_string()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_drain_max_vec_size() {
|
||||
let mut v = Vec::<()>::with_capacity(usize::max_value());
|
||||
unsafe { v.set_len(usize::max_value()); }
|
||||
for _ in v.drain(usize::max_value() - 1..) {
|
||||
unsafe {
|
||||
v.set_len(usize::max_value());
|
||||
}
|
||||
for _ in v.drain(usize::max_value() - 1..) {}
|
||||
assert_eq!(v.len(), usize::max_value() - 1);
|
||||
|
||||
let mut v = Vec::<()>::with_capacity(usize::max_value());
|
||||
unsafe { v.set_len(usize::max_value()); }
|
||||
for _ in v.drain(usize::max_value() - 1..=usize::max_value() - 1) {
|
||||
unsafe {
|
||||
v.set_len(usize::max_value());
|
||||
}
|
||||
for _ in v.drain(usize::max_value() - 1..=usize::max_value() - 1) {}
|
||||
assert_eq!(v.len(), usize::max_value() - 1);
|
||||
}
|
||||
|
||||
|
@ -864,17 +855,12 @@ fn drain_filter_true() {
|
|||
|
||||
#[test]
|
||||
fn drain_filter_complex() {
|
||||
|
||||
{ // [+xxx++++++xxxxx++++x+x++]
|
||||
let mut vec = vec![1,
|
||||
2, 4, 6,
|
||||
7, 9, 11, 13, 15, 17,
|
||||
18, 20, 22, 24, 26,
|
||||
27, 29, 31, 33,
|
||||
34,
|
||||
35,
|
||||
36,
|
||||
37, 39];
|
||||
{
|
||||
// [+xxx++++++xxxxx++++x+x++]
|
||||
let mut vec = vec![
|
||||
1, 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37,
|
||||
39,
|
||||
];
|
||||
|
||||
let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
|
||||
assert_eq!(removed.len(), 10);
|
||||
|
@ -884,15 +870,11 @@ fn drain_filter_complex() {
|
|||
assert_eq!(vec, vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]);
|
||||
}
|
||||
|
||||
{ // [xxx++++++xxxxx++++x+x++]
|
||||
let mut vec = vec![2, 4, 6,
|
||||
7, 9, 11, 13, 15, 17,
|
||||
18, 20, 22, 24, 26,
|
||||
27, 29, 31, 33,
|
||||
34,
|
||||
35,
|
||||
36,
|
||||
37, 39];
|
||||
{
|
||||
// [xxx++++++xxxxx++++x+x++]
|
||||
let mut vec = vec![
|
||||
2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, 39,
|
||||
];
|
||||
|
||||
let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
|
||||
assert_eq!(removed.len(), 10);
|
||||
|
@ -902,14 +884,10 @@ fn drain_filter_complex() {
|
|||
assert_eq!(vec, vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]);
|
||||
}
|
||||
|
||||
{ // [xxx++++++xxxxx++++x+x]
|
||||
let mut vec = vec![2, 4, 6,
|
||||
7, 9, 11, 13, 15, 17,
|
||||
18, 20, 22, 24, 26,
|
||||
27, 29, 31, 33,
|
||||
34,
|
||||
35,
|
||||
36];
|
||||
{
|
||||
// [xxx++++++xxxxx++++x+x]
|
||||
let mut vec =
|
||||
vec![2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36];
|
||||
|
||||
let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
|
||||
assert_eq!(removed.len(), 10);
|
||||
|
@ -919,9 +897,9 @@ fn drain_filter_complex() {
|
|||
assert_eq!(vec, vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35]);
|
||||
}
|
||||
|
||||
{ // [xxxxxxxxxx+++++++++++]
|
||||
let mut vec = vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
|
||||
1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
|
||||
{
|
||||
// [xxxxxxxxxx+++++++++++]
|
||||
let mut vec = vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
|
||||
|
||||
let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
|
||||
assert_eq!(removed.len(), 10);
|
||||
|
@ -931,9 +909,9 @@ fn drain_filter_complex() {
|
|||
assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
|
||||
}
|
||||
|
||||
{ // [+++++++++++xxxxxxxxxx]
|
||||
let mut vec = vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19,
|
||||
2, 4, 6, 8, 10, 12, 14, 16, 18, 20];
|
||||
{
|
||||
// [+++++++++++xxxxxxxxxx]
|
||||
let mut vec = vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20];
|
||||
|
||||
let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
|
||||
assert_eq!(removed.len(), 10);
|
||||
|
@ -1082,7 +1060,6 @@ fn test_reserve_exact() {
|
|||
#[test]
|
||||
#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
|
||||
fn test_try_reserve() {
|
||||
|
||||
// These are the interesting cases:
|
||||
// * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM)
|
||||
// * > isize::MAX should always fail
|
||||
|
@ -1116,23 +1093,30 @@ fn test_try_reserve() {
|
|||
if guards_against_isize {
|
||||
// Check isize::MAX + 1 does count as overflow
|
||||
if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP + 1) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an overflow!") }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an overflow!")
|
||||
}
|
||||
|
||||
// Check usize::MAX does count as overflow
|
||||
if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) {
|
||||
} else { panic!("usize::MAX should trigger an overflow!") }
|
||||
} else {
|
||||
panic!("usize::MAX should trigger an overflow!")
|
||||
}
|
||||
} else {
|
||||
// Check isize::MAX + 1 is an OOM
|
||||
if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP + 1) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an OOM!")
|
||||
}
|
||||
|
||||
// Check usize::MAX is an OOM
|
||||
if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE) {
|
||||
} else { panic!("usize::MAX should trigger an OOM!") }
|
||||
} else {
|
||||
panic!("usize::MAX should trigger an OOM!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
// Same basic idea, but with non-zero len
|
||||
let mut ten_bytes: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
|
@ -1145,33 +1129,42 @@ fn test_try_reserve() {
|
|||
}
|
||||
if guards_against_isize {
|
||||
if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an overflow!"); }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an overflow!");
|
||||
}
|
||||
} else {
|
||||
if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an OOM!")
|
||||
}
|
||||
}
|
||||
// Should always overflow in the add-to-len
|
||||
if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) {
|
||||
} else { panic!("usize::MAX should trigger an overflow!") }
|
||||
} else {
|
||||
panic!("usize::MAX should trigger an overflow!")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
// Same basic idea, but with interesting type size
|
||||
let mut ten_u32s: Vec<u32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
|
||||
if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 10) {
|
||||
if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) {
|
||||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 10) {
|
||||
if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) {
|
||||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
if guards_against_isize {
|
||||
if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an overflow!"); }
|
||||
if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 9) {
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an overflow!");
|
||||
}
|
||||
} else {
|
||||
if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
|
||||
if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP / 4 - 9) {
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an OOM!")
|
||||
}
|
||||
}
|
||||
// Should fail in the mul-by-size
|
||||
if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_USIZE - 20) {
|
||||
|
@ -1179,13 +1172,11 @@ fn test_try_reserve() {
|
|||
panic!("usize::MAX should trigger an overflow!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
|
||||
fn test_try_reserve_exact() {
|
||||
|
||||
// This is exactly the same as test_try_reserve with the method changed.
|
||||
// See that test for comments.
|
||||
|
||||
|
@ -1206,20 +1197,27 @@ fn test_try_reserve_exact() {
|
|||
|
||||
if guards_against_isize {
|
||||
if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP + 1) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an overflow!") }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an overflow!")
|
||||
}
|
||||
|
||||
if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) {
|
||||
} else { panic!("usize::MAX should trigger an overflow!") }
|
||||
} else {
|
||||
panic!("usize::MAX should trigger an overflow!")
|
||||
}
|
||||
} else {
|
||||
if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP + 1) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an OOM!")
|
||||
}
|
||||
|
||||
if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_USIZE) {
|
||||
} else { panic!("usize::MAX should trigger an OOM!") }
|
||||
} else {
|
||||
panic!("usize::MAX should trigger an OOM!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
let mut ten_bytes: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
|
||||
|
@ -1231,36 +1229,46 @@ fn test_try_reserve_exact() {
|
|||
}
|
||||
if guards_against_isize {
|
||||
if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an overflow!"); }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an overflow!");
|
||||
}
|
||||
} else {
|
||||
if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an OOM!")
|
||||
}
|
||||
}
|
||||
if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
|
||||
} else { panic!("usize::MAX should trigger an overflow!") }
|
||||
} else {
|
||||
panic!("usize::MAX should trigger an overflow!")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
let mut ten_u32s: Vec<u32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
|
||||
if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 10) {
|
||||
if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) {
|
||||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 10) {
|
||||
if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) {
|
||||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
if guards_against_isize {
|
||||
if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an overflow!"); }
|
||||
if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9) {
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an overflow!");
|
||||
}
|
||||
} else {
|
||||
if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
|
||||
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
|
||||
if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9) {
|
||||
} else {
|
||||
panic!("isize::MAX + 1 should trigger an OOM!")
|
||||
}
|
||||
}
|
||||
if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) {
|
||||
} else { panic!("usize::MAX should trigger an overflow!") }
|
||||
} else {
|
||||
panic!("usize::MAX should trigger an overflow!")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1311,18 +1319,11 @@ fn vec_macro_repeating_null_raw_fat_pointer() {
|
|||
// Polyfill for https://github.com/rust-lang/rfcs/pull/2580
|
||||
|
||||
fn ptr_metadata(ptr: *mut dyn Fn()) -> *mut () {
|
||||
unsafe {
|
||||
std::mem::transmute::<*mut dyn Fn(), DynRepr>(ptr).vtable
|
||||
}
|
||||
unsafe { std::mem::transmute::<*mut dyn Fn(), DynRepr>(ptr).vtable }
|
||||
}
|
||||
|
||||
fn ptr_from_raw_parts(data: *mut (), vtable: *mut()) -> *mut dyn Fn() {
|
||||
unsafe {
|
||||
std::mem::transmute::<DynRepr, *mut dyn Fn()>(DynRepr {
|
||||
data,
|
||||
vtable
|
||||
})
|
||||
}
|
||||
fn ptr_from_raw_parts(data: *mut (), vtable: *mut ()) -> *mut dyn Fn() {
|
||||
unsafe { std::mem::transmute::<DynRepr, *mut dyn Fn()>(DynRepr { data, vtable }) }
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
|
|
@ -64,14 +64,14 @@ use core::intrinsics::{arith_offset, assume};
|
|||
use core::iter::{FromIterator, FusedIterator, TrustedLen};
|
||||
use core::marker::PhantomData;
|
||||
use core::mem;
|
||||
use core::ops::{self, Index, IndexMut, RangeBounds};
|
||||
use core::ops::Bound::{Excluded, Included, Unbounded};
|
||||
use core::ops::{self, Index, IndexMut, RangeBounds};
|
||||
use core::ptr::{self, NonNull};
|
||||
use core::slice::{self, SliceIndex};
|
||||
|
||||
use crate::borrow::{ToOwned, Cow};
|
||||
use crate::collections::TryReserveError;
|
||||
use crate::borrow::{Cow, ToOwned};
|
||||
use crate::boxed::Box;
|
||||
use crate::collections::TryReserveError;
|
||||
use crate::raw_vec::RawVec;
|
||||
|
||||
/// A contiguous growable array type, written `Vec<T>` but pronounced 'vector'.
|
||||
|
@ -318,10 +318,7 @@ impl<T> Vec<T> {
|
|||
#[rustc_const_stable(feature = "const_vec_new", since = "1.32.0")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const fn new() -> Vec<T> {
|
||||
Vec {
|
||||
buf: RawVec::NEW,
|
||||
len: 0,
|
||||
}
|
||||
Vec { buf: RawVec::NEW, len: 0 }
|
||||
}
|
||||
|
||||
/// Constructs a new, empty `Vec<T>` with the specified capacity.
|
||||
|
@ -355,10 +352,7 @@ impl<T> Vec<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn with_capacity(capacity: usize) -> Vec<T> {
|
||||
Vec {
|
||||
buf: RawVec::with_capacity(capacity),
|
||||
len: 0,
|
||||
}
|
||||
Vec { buf: RawVec::with_capacity(capacity), len: 0 }
|
||||
}
|
||||
|
||||
/// Decomposes a `Vec<T>` into its raw components.
|
||||
|
@ -459,10 +453,7 @@ impl<T> Vec<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Vec<T> {
|
||||
Vec {
|
||||
buf: RawVec::from_raw_parts(ptr, capacity),
|
||||
len: length,
|
||||
}
|
||||
Vec { buf: RawVec::from_raw_parts(ptr, capacity), len: length }
|
||||
}
|
||||
|
||||
/// Returns the number of elements the vector can hold without
|
||||
|
@ -559,7 +550,7 @@ impl<T> Vec<T> {
|
|||
/// }
|
||||
/// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
|
||||
/// ```
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
|
||||
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
|
||||
self.buf.try_reserve(self.len, additional)
|
||||
}
|
||||
|
@ -599,8 +590,8 @@ impl<T> Vec<T> {
|
|||
/// }
|
||||
/// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
|
||||
/// ```
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
|
||||
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
|
||||
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
|
||||
self.buf.try_reserve_exact(self.len, additional)
|
||||
}
|
||||
|
||||
|
@ -647,7 +638,7 @@ impl<T> Vec<T> {
|
|||
/// vec.shrink_to(0);
|
||||
/// assert!(vec.capacity() >= 3);
|
||||
/// ```
|
||||
#[unstable(feature = "shrink_to", reason = "new API", issue="56431")]
|
||||
#[unstable(feature = "shrink_to", reason = "new API", issue = "56431")]
|
||||
pub fn shrink_to(&mut self, min_capacity: usize) {
|
||||
self.buf.shrink_to_fit(cmp::max(self.len, min_capacity));
|
||||
}
|
||||
|
@ -812,7 +803,9 @@ impl<T> Vec<T> {
|
|||
// We shadow the slice method of the same name to avoid going through
|
||||
// `deref`, which creates an intermediate reference.
|
||||
let ptr = self.buf.ptr();
|
||||
unsafe { assume(!ptr.is_null()); }
|
||||
unsafe {
|
||||
assume(!ptr.is_null());
|
||||
}
|
||||
ptr
|
||||
}
|
||||
|
||||
|
@ -846,7 +839,9 @@ impl<T> Vec<T> {
|
|||
// We shadow the slice method of the same name to avoid going through
|
||||
// `deref_mut`, which creates an intermediate reference.
|
||||
let ptr = self.buf.ptr();
|
||||
unsafe { assume(!ptr.is_null()); }
|
||||
unsafe {
|
||||
assume(!ptr.is_null());
|
||||
}
|
||||
ptr
|
||||
}
|
||||
|
||||
|
@ -1074,7 +1069,8 @@ impl<T> Vec<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn retain<F>(&mut self, mut f: F)
|
||||
where F: FnMut(&T) -> bool
|
||||
where
|
||||
F: FnMut(&T) -> bool,
|
||||
{
|
||||
let len = self.len();
|
||||
let mut del = 0;
|
||||
|
@ -1110,7 +1106,11 @@ impl<T> Vec<T> {
|
|||
/// ```
|
||||
#[stable(feature = "dedup_by", since = "1.16.0")]
|
||||
#[inline]
|
||||
pub fn dedup_by_key<F, K>(&mut self, mut key: F) where F: FnMut(&mut T) -> K, K: PartialEq {
|
||||
pub fn dedup_by_key<F, K>(&mut self, mut key: F)
|
||||
where
|
||||
F: FnMut(&mut T) -> K,
|
||||
K: PartialEq,
|
||||
{
|
||||
self.dedup_by(|a, b| key(a) == key(b))
|
||||
}
|
||||
|
||||
|
@ -1133,7 +1133,10 @@ impl<T> Vec<T> {
|
|||
/// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
|
||||
/// ```
|
||||
#[stable(feature = "dedup_by", since = "1.16.0")]
|
||||
pub fn dedup_by<F>(&mut self, same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {
|
||||
pub fn dedup_by<F>(&mut self, same_bucket: F)
|
||||
where
|
||||
F: FnMut(&mut T, &mut T) -> bool,
|
||||
{
|
||||
let len = {
|
||||
let (dedup, _) = self.as_mut_slice().partition_dedup_by(same_bucket);
|
||||
dedup.len()
|
||||
|
@ -1256,7 +1259,8 @@ impl<T> Vec<T> {
|
|||
/// ```
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
|
||||
where R: RangeBounds<usize>
|
||||
where
|
||||
R: RangeBounds<usize>,
|
||||
{
|
||||
// Memory safety
|
||||
//
|
||||
|
@ -1272,12 +1276,12 @@ impl<T> Vec<T> {
|
|||
let start = match range.start_bound() {
|
||||
Included(&n) => n,
|
||||
Excluded(&n) => n + 1,
|
||||
Unbounded => 0,
|
||||
Unbounded => 0,
|
||||
};
|
||||
let end = match range.end_bound() {
|
||||
Included(&n) => n + 1,
|
||||
Excluded(&n) => n,
|
||||
Unbounded => len,
|
||||
Unbounded => len,
|
||||
};
|
||||
assert!(start <= end);
|
||||
assert!(end <= len);
|
||||
|
@ -1287,8 +1291,7 @@ impl<T> Vec<T> {
|
|||
self.set_len(start);
|
||||
// Use the borrow in the IterMut to indicate borrowing behavior of the
|
||||
// whole Drain iterator (like &mut T).
|
||||
let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(start),
|
||||
end - start);
|
||||
let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(start), end - start);
|
||||
Drain {
|
||||
tail_start: end,
|
||||
tail_len: len - end,
|
||||
|
@ -1380,9 +1383,7 @@ impl<T> Vec<T> {
|
|||
self.set_len(at);
|
||||
other.set_len(other_len);
|
||||
|
||||
ptr::copy_nonoverlapping(self.as_ptr().add(at),
|
||||
other.as_mut_ptr(),
|
||||
other.len());
|
||||
ptr::copy_nonoverlapping(self.as_ptr().add(at), other.as_mut_ptr(), other.len());
|
||||
}
|
||||
other
|
||||
}
|
||||
|
@ -1418,7 +1419,8 @@ impl<T> Vec<T> {
|
|||
/// [`Clone`]: ../../std/clone/trait.Clone.html
|
||||
#[stable(feature = "vec_resize_with", since = "1.33.0")]
|
||||
pub fn resize_with<F>(&mut self, new_len: usize, f: F)
|
||||
where F: FnMut() -> T
|
||||
where
|
||||
F: FnMut() -> T,
|
||||
{
|
||||
let len = self.len();
|
||||
if new_len > len {
|
||||
|
@ -1455,7 +1457,7 @@ impl<T> Vec<T> {
|
|||
#[inline]
|
||||
pub fn leak<'a>(vec: Vec<T>) -> &'a mut [T]
|
||||
where
|
||||
T: 'a // Technically not needed, but kept to be explicit.
|
||||
T: 'a, // Technically not needed, but kept to be explicit.
|
||||
{
|
||||
Box::leak(vec.into_boxed_slice())
|
||||
}
|
||||
|
@ -1553,9 +1555,12 @@ impl<T: Default> Vec<T> {
|
|||
/// [`Default`]: ../../std/default/trait.Default.html
|
||||
/// [`Clone`]: ../../std/clone/trait.Clone.html
|
||||
#[unstable(feature = "vec_resize_default", issue = "41758")]
|
||||
#[rustc_deprecated(reason = "This is moving towards being removed in favor \
|
||||
#[rustc_deprecated(
|
||||
reason = "This is moving towards being removed in favor \
|
||||
of `.resize_with(Default::default)`. If you disagree, please comment \
|
||||
in the tracking issue.", since = "1.33.0")]
|
||||
in the tracking issue.",
|
||||
since = "1.33.0"
|
||||
)]
|
||||
pub fn resize_default(&mut self, new_len: usize) {
|
||||
let len = self.len();
|
||||
|
||||
|
@ -1575,20 +1580,32 @@ trait ExtendWith<T> {
|
|||
|
||||
struct ExtendElement<T>(T);
|
||||
impl<T: Clone> ExtendWith<T> for ExtendElement<T> {
|
||||
fn next(&mut self) -> T { self.0.clone() }
|
||||
fn last(self) -> T { self.0 }
|
||||
fn next(&mut self) -> T {
|
||||
self.0.clone()
|
||||
}
|
||||
fn last(self) -> T {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
struct ExtendDefault;
|
||||
impl<T: Default> ExtendWith<T> for ExtendDefault {
|
||||
fn next(&mut self) -> T { Default::default() }
|
||||
fn last(self) -> T { Default::default() }
|
||||
fn next(&mut self) -> T {
|
||||
Default::default()
|
||||
}
|
||||
fn last(self) -> T {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
struct ExtendFunc<F>(F);
|
||||
impl<T, F: FnMut() -> T> ExtendWith<T> for ExtendFunc<F> {
|
||||
fn next(&mut self) -> T { (self.0)() }
|
||||
fn last(mut self) -> T { (self.0)() }
|
||||
fn next(&mut self) -> T {
|
||||
(self.0)()
|
||||
}
|
||||
fn last(mut self) -> T {
|
||||
(self.0)()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Vec<T> {
|
||||
|
@ -1718,10 +1735,7 @@ impl SpecFromElem for u8 {
|
|||
#[inline]
|
||||
fn from_elem(elem: u8, n: usize) -> Vec<u8> {
|
||||
if elem == 0 {
|
||||
return Vec {
|
||||
buf: RawVec::with_capacity_zeroed(n),
|
||||
len: n,
|
||||
}
|
||||
return Vec { buf: RawVec::with_capacity_zeroed(n), len: n };
|
||||
}
|
||||
unsafe {
|
||||
let mut v = Vec::with_capacity(n);
|
||||
|
@ -1736,10 +1750,7 @@ impl<T: Clone + IsZero> SpecFromElem for T {
|
|||
#[inline]
|
||||
fn from_elem(elem: T, n: usize) -> Vec<T> {
|
||||
if elem.is_zero() {
|
||||
return Vec {
|
||||
buf: RawVec::with_capacity_zeroed(n),
|
||||
len: n,
|
||||
}
|
||||
return Vec { buf: RawVec::with_capacity_zeroed(n), len: n };
|
||||
}
|
||||
let mut v = Vec::with_capacity(n);
|
||||
v.extend_with(n, ExtendElement(elem));
|
||||
|
@ -1760,7 +1771,7 @@ macro_rules! impl_is_zero {
|
|||
$is_zero(*self)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_is_zero!(i8, |x| x == 0);
|
||||
|
@ -1821,7 +1832,6 @@ unsafe impl<T: ?Sized> IsZero for Option<Box<T>> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Common trait implementations for Vec
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1857,8 +1867,8 @@ impl<T: Hash> Hash for Vec<T> {
|
|||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented(
|
||||
message="vector indices are of type `usize` or ranges of `usize`",
|
||||
label="vector indices are of type `usize` or ranges of `usize`",
|
||||
message = "vector indices are of type `usize` or ranges of `usize`",
|
||||
label = "vector indices are of type `usize` or ranges of `usize`"
|
||||
)]
|
||||
impl<T, I: SliceIndex<[T]>> Index<I> for Vec<T> {
|
||||
type Output = I::Output;
|
||||
|
@ -1871,8 +1881,8 @@ impl<T, I: SliceIndex<[T]>> Index<I> for Vec<T> {
|
|||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented(
|
||||
message="vector indices are of type `usize` or ranges of `usize`",
|
||||
label="vector indices are of type `usize` or ranges of `usize`",
|
||||
message = "vector indices are of type `usize` or ranges of `usize`",
|
||||
label = "vector indices are of type `usize` or ranges of `usize`"
|
||||
)]
|
||||
impl<T, I: SliceIndex<[T]>> IndexMut<I> for Vec<T> {
|
||||
#[inline]
|
||||
|
@ -1886,18 +1896,14 @@ impl<T> ops::Deref for Vec<T> {
|
|||
type Target = [T];
|
||||
|
||||
fn deref(&self) -> &[T] {
|
||||
unsafe {
|
||||
slice::from_raw_parts(self.as_ptr(), self.len)
|
||||
}
|
||||
unsafe { slice::from_raw_parts(self.as_ptr(), self.len) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> ops::DerefMut for Vec<T> {
|
||||
fn deref_mut(&mut self) -> &mut [T] {
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(self.as_mut_ptr(), self.len)
|
||||
}
|
||||
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1984,7 +1990,8 @@ trait SpecExtend<T, I> {
|
|||
}
|
||||
|
||||
impl<T, I> SpecExtend<T, I> for Vec<T>
|
||||
where I: Iterator<Item=T>,
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
{
|
||||
default fn from_iter(mut iterator: I) -> Self {
|
||||
// Unroll the first iteration, as the vector is going to be
|
||||
|
@ -2014,7 +2021,8 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
|
|||
}
|
||||
|
||||
impl<T, I> SpecExtend<T, I> for Vec<T>
|
||||
where I: TrustedLen<Item=T>,
|
||||
where
|
||||
I: TrustedLen<Item = T>,
|
||||
{
|
||||
default fn from_iter(iterator: I) -> Self {
|
||||
let mut vector = Vec::new();
|
||||
|
@ -2026,9 +2034,12 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
|
|||
// This is the case for a TrustedLen iterator.
|
||||
let (low, high) = iterator.size_hint();
|
||||
if let Some(high_value) = high {
|
||||
debug_assert_eq!(low, high_value,
|
||||
"TrustedLen iterator's size hint is not exact: {:?}",
|
||||
(low, high));
|
||||
debug_assert_eq!(
|
||||
low,
|
||||
high_value,
|
||||
"TrustedLen iterator's size hint is not exact: {:?}",
|
||||
(low, high)
|
||||
);
|
||||
}
|
||||
if let Some(additional) = high {
|
||||
self.reserve(additional);
|
||||
|
@ -2055,9 +2066,7 @@ impl<T> SpecExtend<T, IntoIter<T>> for Vec<T> {
|
|||
// has not been advanced at all.
|
||||
if iterator.buf.as_ptr() as *const _ == iterator.ptr {
|
||||
unsafe {
|
||||
let vec = Vec::from_raw_parts(iterator.buf.as_ptr(),
|
||||
iterator.len(),
|
||||
iterator.cap);
|
||||
let vec = Vec::from_raw_parts(iterator.buf.as_ptr(), iterator.len(), iterator.cap);
|
||||
mem::forget(iterator);
|
||||
vec
|
||||
}
|
||||
|
@ -2077,8 +2086,9 @@ impl<T> SpecExtend<T, IntoIter<T>> for Vec<T> {
|
|||
}
|
||||
|
||||
impl<'a, T: 'a, I> SpecExtend<&'a T, I> for Vec<T>
|
||||
where I: Iterator<Item=&'a T>,
|
||||
T: Clone,
|
||||
where
|
||||
I: Iterator<Item = &'a T>,
|
||||
T: Clone,
|
||||
{
|
||||
default fn from_iter(iterator: I) -> Self {
|
||||
SpecExtend::from_iter(iterator.cloned())
|
||||
|
@ -2090,7 +2100,8 @@ impl<'a, T: 'a, I> SpecExtend<&'a T, I> for Vec<T>
|
|||
}
|
||||
|
||||
impl<'a, T: 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec<T>
|
||||
where T: Copy,
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) {
|
||||
let slice = iterator.as_slice();
|
||||
|
@ -2162,12 +2173,11 @@ impl<T> Vec<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "vec_splice", since = "1.21.0")]
|
||||
pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter>
|
||||
where R: RangeBounds<usize>, I: IntoIterator<Item=T>
|
||||
where
|
||||
R: RangeBounds<usize>,
|
||||
I: IntoIterator<Item = T>,
|
||||
{
|
||||
Splice {
|
||||
drain: self.drain(range),
|
||||
replace_with: replace_with.into_iter(),
|
||||
}
|
||||
Splice { drain: self.drain(range), replace_with: replace_with.into_iter() }
|
||||
}
|
||||
|
||||
/// Creates an iterator which uses a closure to determine if an element should be removed.
|
||||
|
@ -2217,21 +2227,17 @@ impl<T> Vec<T> {
|
|||
/// ```
|
||||
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
|
||||
pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F>
|
||||
where F: FnMut(&mut T) -> bool,
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
let old_len = self.len();
|
||||
|
||||
// Guard against us getting leaked (leak amplification)
|
||||
unsafe { self.set_len(0); }
|
||||
|
||||
DrainFilter {
|
||||
vec: self,
|
||||
idx: 0,
|
||||
del: 0,
|
||||
old_len,
|
||||
pred: filter,
|
||||
panic_flag: false,
|
||||
unsafe {
|
||||
self.set_len(0);
|
||||
}
|
||||
|
||||
DrainFilter { vec: self, idx: 0, del: 0, old_len, pred: filter, panic_flag: false }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2380,7 +2386,10 @@ impl<T: Clone> From<&mut [T]> for Vec<T> {
|
|||
}
|
||||
|
||||
#[stable(feature = "vec_from_cow_slice", since = "1.14.0")]
|
||||
impl<'a, T> From<Cow<'a, [T]>> for Vec<T> where [T]: ToOwned<Owned=Vec<T>> {
|
||||
impl<'a, T> From<Cow<'a, [T]>> for Vec<T>
|
||||
where
|
||||
[T]: ToOwned<Owned = Vec<T>>,
|
||||
{
|
||||
fn from(s: Cow<'a, [T]>) -> Vec<T> {
|
||||
s.into_owned()
|
||||
}
|
||||
|
@ -2437,7 +2446,10 @@ impl<'a, T: Clone> From<&'a Vec<T>> for Cow<'a, [T]> {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> FromIterator<T> for Cow<'a, [T]> where T: Clone {
|
||||
impl<'a, T> FromIterator<T> for Cow<'a, [T]>
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
fn from_iter<I: IntoIterator<Item = T>>(it: I) -> Cow<'a, [T]> {
|
||||
Cow::Owned(FromIterator::from_iter(it))
|
||||
}
|
||||
|
@ -2466,9 +2478,7 @@ pub struct IntoIter<T> {
|
|||
#[stable(feature = "vec_intoiter_debug", since = "1.13.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("IntoIter")
|
||||
.field(&self.as_slice())
|
||||
.finish()
|
||||
f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2486,9 +2496,7 @@ impl<T> IntoIter<T> {
|
|||
/// ```
|
||||
#[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")]
|
||||
pub fn as_slice(&self) -> &[T] {
|
||||
unsafe {
|
||||
slice::from_raw_parts(self.ptr, self.len())
|
||||
}
|
||||
unsafe { slice::from_raw_parts(self.ptr, self.len()) }
|
||||
}
|
||||
|
||||
/// Returns the remaining items of this iterator as a mutable slice.
|
||||
|
@ -2506,9 +2514,7 @@ impl<T> IntoIter<T> {
|
|||
/// ```
|
||||
#[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")]
|
||||
pub fn as_mut_slice(&mut self) -> &mut [T] {
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(self.ptr as *mut T, self.len())
|
||||
}
|
||||
unsafe { slice::from_raw_parts_mut(self.ptr as *mut T, self.len()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2636,9 +2642,7 @@ pub struct Drain<'a, T: 'a> {
|
|||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for Drain<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Drain")
|
||||
.field(&self.iter.as_slice())
|
||||
.finish()
|
||||
f.debug_tuple("Drain").field(&self.iter.as_slice()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2711,7 +2715,6 @@ impl<T> Drop for Drain<'_, T> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
impl<T> ExactSizeIterator for Drain<'_, T> {
|
||||
fn is_empty(&self) -> bool {
|
||||
|
@ -2762,7 +2765,6 @@ impl<I: Iterator> DoubleEndedIterator for Splice<'_, I> {
|
|||
#[stable(feature = "vec_splice", since = "1.21.0")]
|
||||
impl<I: Iterator> ExactSizeIterator for Splice<'_, I> {}
|
||||
|
||||
|
||||
#[stable(feature = "vec_splice", since = "1.21.0")]
|
||||
impl<I: Iterator> Drop for Splice<'_, I> {
|
||||
fn drop(&mut self) {
|
||||
|
@ -2771,21 +2773,21 @@ impl<I: Iterator> Drop for Splice<'_, I> {
|
|||
unsafe {
|
||||
if self.drain.tail_len == 0 {
|
||||
self.drain.vec.as_mut().extend(self.replace_with.by_ref());
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
// First fill the range left by drain().
|
||||
if !self.drain.fill(&mut self.replace_with) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
// There may be more elements. Use the lower bound as an estimate.
|
||||
// FIXME: Is the upper bound a better guess? Or something else?
|
||||
let (lower_bound, _upper_bound) = self.replace_with.size_hint();
|
||||
if lower_bound > 0 {
|
||||
if lower_bound > 0 {
|
||||
self.drain.move_tail(lower_bound);
|
||||
if !self.drain.fill(&mut self.replace_with) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2810,20 +2812,19 @@ impl<T> Drain<'_, T> {
|
|||
/// that have been moved out.
|
||||
/// Fill that range as much as possible with new elements from the `replace_with` iterator.
|
||||
/// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.)
|
||||
unsafe fn fill<I: Iterator<Item=T>>(&mut self, replace_with: &mut I) -> bool {
|
||||
unsafe fn fill<I: Iterator<Item = T>>(&mut self, replace_with: &mut I) -> bool {
|
||||
let vec = self.vec.as_mut();
|
||||
let range_start = vec.len;
|
||||
let range_end = self.tail_start;
|
||||
let range_slice = slice::from_raw_parts_mut(
|
||||
vec.as_mut_ptr().add(range_start),
|
||||
range_end - range_start);
|
||||
let range_slice =
|
||||
slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start);
|
||||
|
||||
for place in range_slice {
|
||||
if let Some(new_item) = replace_with.next() {
|
||||
ptr::write(place, new_item);
|
||||
vec.len += 1;
|
||||
} else {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
|
@ -2847,7 +2848,8 @@ impl<T> Drain<'_, T> {
|
|||
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
|
||||
#[derive(Debug)]
|
||||
pub struct DrainFilter<'a, T, F>
|
||||
where F: FnMut(&mut T) -> bool,
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
vec: &'a mut Vec<T>,
|
||||
/// The index of the item that will be inspected by the next call to `next`.
|
||||
|
@ -2868,7 +2870,8 @@ pub struct DrainFilter<'a, T, F>
|
|||
|
||||
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
|
||||
impl<T, F> Iterator for DrainFilter<'_, T, F>
|
||||
where F: FnMut(&mut T) -> bool,
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
|
@ -2905,19 +2908,20 @@ impl<T, F> Iterator for DrainFilter<'_, T, F>
|
|||
|
||||
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
|
||||
impl<T, F> Drop for DrainFilter<'_, T, F>
|
||||
where F: FnMut(&mut T) -> bool,
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
struct BackshiftOnDrop<'a, 'b, T, F>
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
drain: &'b mut DrainFilter<'a, T, F>,
|
||||
}
|
||||
|
||||
impl<'a, 'b, T, F> Drop for BackshiftOnDrop<'a, 'b, T, F>
|
||||
where
|
||||
F: FnMut(&mut T) -> bool
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
|
@ -2939,9 +2943,7 @@ impl<T, F> Drop for DrainFilter<'_, T, F>
|
|||
}
|
||||
}
|
||||
|
||||
let backshift = BackshiftOnDrop {
|
||||
drain: self
|
||||
};
|
||||
let backshift = BackshiftOnDrop { drain: self };
|
||||
|
||||
// Attempt to consume any remaining elements if the filter predicate
|
||||
// has not yet panicked. We'll backshift any remaining elements
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
//! This crate implements `TypedArena`, a simple arena that can only hold
|
||||
//! objects of a single type.
|
||||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
|
||||
test(no_crate_inject, attr(deny(warnings))))]
|
||||
|
||||
#![doc(
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/",
|
||||
test(no_crate_inject, attr(deny(warnings)))
|
||||
)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(raw_vec_internals)]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
extern crate alloc;
|
||||
|
@ -61,10 +61,7 @@ struct TypedArenaChunk<T> {
|
|||
impl<T> TypedArenaChunk<T> {
|
||||
#[inline]
|
||||
unsafe fn new(capacity: usize) -> TypedArenaChunk<T> {
|
||||
TypedArenaChunk {
|
||||
storage: RawVec::with_capacity(capacity),
|
||||
entries: 0,
|
||||
}
|
||||
TypedArenaChunk { storage: RawVec::with_capacity(capacity), entries: 0 }
|
||||
}
|
||||
|
||||
/// Destroys this arena chunk.
|
||||
|
@ -133,9 +130,7 @@ impl<T> TypedArena<T> {
|
|||
|
||||
unsafe {
|
||||
if mem::size_of::<T>() == 0 {
|
||||
self.ptr
|
||||
.set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1)
|
||||
as *mut T);
|
||||
self.ptr.set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1) as *mut T);
|
||||
let ptr = mem::align_of::<T>() as *mut T;
|
||||
// Don't drop the object. This `write` is equivalent to `forget`.
|
||||
ptr::write(ptr, object);
|
||||
|
@ -260,7 +255,7 @@ impl<T> TypedArena<T> {
|
|||
self.clear_last_chunk(&mut last_chunk);
|
||||
let len = chunks_borrow.len();
|
||||
// If `T` is ZST, code below has no effect.
|
||||
for mut chunk in chunks_borrow.drain(..len-1) {
|
||||
for mut chunk in chunks_borrow.drain(..len - 1) {
|
||||
chunk.destroy(chunk.entries);
|
||||
}
|
||||
}
|
||||
|
@ -360,10 +355,7 @@ impl DroplessArena {
|
|||
let (chunk, mut new_capacity);
|
||||
if let Some(last_chunk) = chunks.last_mut() {
|
||||
let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize;
|
||||
if last_chunk
|
||||
.storage
|
||||
.reserve_in_place(used_bytes, needed_bytes)
|
||||
{
|
||||
if last_chunk.storage.reserve_in_place(used_bytes, needed_bytes) {
|
||||
self.end.set(last_chunk.end());
|
||||
return;
|
||||
} else {
|
||||
|
@ -399,9 +391,7 @@ impl DroplessArena {
|
|||
|
||||
let ptr = self.ptr.get();
|
||||
// Set the pointer past ourselves
|
||||
self.ptr.set(
|
||||
intrinsics::arith_offset(self.ptr.get(), bytes as isize) as *mut u8,
|
||||
);
|
||||
self.ptr.set(intrinsics::arith_offset(self.ptr.get(), bytes as isize) as *mut u8);
|
||||
slice::from_raw_parts_mut(ptr, bytes)
|
||||
}
|
||||
}
|
||||
|
@ -410,9 +400,7 @@ impl DroplessArena {
|
|||
pub fn alloc<T>(&self, object: T) -> &mut T {
|
||||
assert!(!mem::needs_drop::<T>());
|
||||
|
||||
let mem = self.alloc_raw(
|
||||
mem::size_of::<T>(),
|
||||
mem::align_of::<T>()) as *mut _ as *mut T;
|
||||
let mem = self.alloc_raw(mem::size_of::<T>(), mem::align_of::<T>()) as *mut _ as *mut T;
|
||||
|
||||
unsafe {
|
||||
// Write into uninitialized memory.
|
||||
|
@ -437,9 +425,8 @@ impl DroplessArena {
|
|||
assert!(mem::size_of::<T>() != 0);
|
||||
assert!(!slice.is_empty());
|
||||
|
||||
let mem = self.alloc_raw(
|
||||
slice.len() * mem::size_of::<T>(),
|
||||
mem::align_of::<T>()) as *mut _ as *mut T;
|
||||
let mem = self.alloc_raw(slice.len() * mem::size_of::<T>(), mem::align_of::<T>()) as *mut _
|
||||
as *mut T;
|
||||
|
||||
unsafe {
|
||||
let arena_slice = slice::from_raw_parts_mut(mem, slice.len());
|
||||
|
@ -484,13 +471,11 @@ impl DroplessArena {
|
|||
let len = min;
|
||||
|
||||
if len == 0 {
|
||||
return &mut []
|
||||
return &mut [];
|
||||
}
|
||||
let size = len.checked_mul(mem::size_of::<T>()).unwrap();
|
||||
let mem = self.alloc_raw(size, mem::align_of::<T>()) as *mut _ as *mut T;
|
||||
unsafe {
|
||||
self.write_from_iter(iter, len, mem)
|
||||
}
|
||||
unsafe { self.write_from_iter(iter, len, mem) }
|
||||
}
|
||||
(_, _) => {
|
||||
cold_path(move || -> &mut [T] {
|
||||
|
@ -502,10 +487,9 @@ impl DroplessArena {
|
|||
// the content of the SmallVec
|
||||
unsafe {
|
||||
let len = vec.len();
|
||||
let start_ptr = self.alloc_raw(
|
||||
len * mem::size_of::<T>(),
|
||||
mem::align_of::<T>()
|
||||
) as *mut _ as *mut T;
|
||||
let start_ptr = self
|
||||
.alloc_raw(len * mem::size_of::<T>(), mem::align_of::<T>())
|
||||
as *mut _ as *mut T;
|
||||
vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
|
||||
vec.set_len(0);
|
||||
slice::from_raw_parts_mut(start_ptr, len)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
extern crate test;
|
||||
use test::Bencher;
|
||||
use super::TypedArena;
|
||||
use std::cell::Cell;
|
||||
use test::Bencher;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
|
@ -53,9 +53,7 @@ fn test_arena_alloc_nested() {
|
|||
|
||||
let arena = Wrap(TypedArena::default());
|
||||
|
||||
let result = arena.alloc_outer(|| Outer {
|
||||
inner: arena.alloc_inner(|| Inner { value: 10 }),
|
||||
});
|
||||
let result = arena.alloc_outer(|| Outer { inner: arena.alloc_inner(|| Inner { value: 10 }) });
|
||||
|
||||
assert_eq!(result.inner.value, 10);
|
||||
}
|
||||
|
@ -91,10 +89,7 @@ struct Noncopy {
|
|||
pub fn test_noncopy() {
|
||||
let arena = TypedArena::default();
|
||||
for _ in 0..100000 {
|
||||
arena.alloc(Noncopy {
|
||||
string: "hello world".to_string(),
|
||||
array: vec![1, 2, 3, 4, 5],
|
||||
});
|
||||
arena.alloc(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,19 +190,14 @@ fn test_typed_arena_drop_small_count() {
|
|||
pub fn bench_noncopy(b: &mut Bencher) {
|
||||
let arena = TypedArena::default();
|
||||
b.iter(|| {
|
||||
arena.alloc(Noncopy {
|
||||
string: "hello world".to_string(),
|
||||
array: vec![1, 2, 3, 4, 5],
|
||||
})
|
||||
arena.alloc(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] })
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn bench_noncopy_nonarena(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let _: Box<_> = Box::new(Noncopy {
|
||||
string: "hello world".to_string(),
|
||||
array: vec![1, 2, 3, 4, 5],
|
||||
});
|
||||
let _: Box<_> =
|
||||
Box::new(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] });
|
||||
})
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
use crate::cmp;
|
||||
use crate::fmt;
|
||||
use crate::mem;
|
||||
use crate::usize;
|
||||
use crate::ptr::{self, NonNull};
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::ptr::{self, NonNull};
|
||||
use crate::usize;
|
||||
|
||||
/// Represents the combination of a starting address and
|
||||
/// a total capacity of the returned block.
|
||||
|
@ -88,9 +88,7 @@ impl Layout {
|
|||
return Err(LayoutErr { private: () });
|
||||
}
|
||||
|
||||
unsafe {
|
||||
Ok(Layout::from_size_align_unchecked(size, align))
|
||||
}
|
||||
unsafe { Ok(Layout::from_size_align_unchecked(size, align)) }
|
||||
}
|
||||
|
||||
/// Creates a layout, bypassing all checks.
|
||||
|
@ -109,12 +107,16 @@ impl Layout {
|
|||
/// The minimum size in bytes for a memory block of this layout.
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[inline]
|
||||
pub fn size(&self) -> usize { self.size_ }
|
||||
pub fn size(&self) -> usize {
|
||||
self.size_
|
||||
}
|
||||
|
||||
/// The minimum byte alignment for a memory block of this layout.
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[inline]
|
||||
pub fn align(&self) -> usize { self.align_.get() }
|
||||
pub fn align(&self) -> usize {
|
||||
self.align_.get()
|
||||
}
|
||||
|
||||
/// Constructs a `Layout` suitable for holding a value of type `T`.
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
|
@ -126,9 +128,7 @@ impl Layout {
|
|||
// result use the unchecked constructor here to avoid inserting code
|
||||
// that panics if it isn't optimized well enough.
|
||||
debug_assert!(Layout::from_size_align(size, align).is_ok());
|
||||
unsafe {
|
||||
Layout::from_size_align_unchecked(size, align)
|
||||
}
|
||||
unsafe { Layout::from_size_align_unchecked(size, align) }
|
||||
}
|
||||
|
||||
/// Produces layout describing a record that could be used to
|
||||
|
@ -140,9 +140,7 @@ impl Layout {
|
|||
let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
|
||||
// See rationale in `new` for why this is using an unsafe variant below
|
||||
debug_assert!(Layout::from_size_align(size, align).is_ok());
|
||||
unsafe {
|
||||
Layout::from_size_align_unchecked(size, align)
|
||||
}
|
||||
unsafe { Layout::from_size_align_unchecked(size, align) }
|
||||
}
|
||||
|
||||
/// Creates a layout describing the record that can hold a value
|
||||
|
@ -206,8 +204,7 @@ impl Layout {
|
|||
// size and padding overflow in the above manner should cause
|
||||
// the allocator to yield an error anyway.)
|
||||
|
||||
let len_rounded_up = len.wrapping_add(align).wrapping_sub(1)
|
||||
& !align.wrapping_sub(1);
|
||||
let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1);
|
||||
len_rounded_up.wrapping_sub(len)
|
||||
}
|
||||
|
||||
|
@ -245,8 +242,7 @@ impl Layout {
|
|||
// > must not overflow (i.e., the rounded value must be less than
|
||||
// > `usize::MAX`)
|
||||
let padded_size = self.size() + self.padding_needed_for(self.align());
|
||||
let alloc_size = padded_size.checked_mul(n)
|
||||
.ok_or(LayoutErr { private: () })?;
|
||||
let alloc_size = padded_size.checked_mul(n).ok_or(LayoutErr { private: () })?;
|
||||
|
||||
unsafe {
|
||||
// self.align is already known to be valid and alloc_size has been
|
||||
|
@ -275,10 +271,8 @@ impl Layout {
|
|||
let new_align = cmp::max(self.align(), next.align());
|
||||
let pad = self.padding_needed_for(next.align());
|
||||
|
||||
let offset = self.size().checked_add(pad)
|
||||
.ok_or(LayoutErr { private: () })?;
|
||||
let new_size = offset.checked_add(next.size())
|
||||
.ok_or(LayoutErr { private: () })?;
|
||||
let offset = self.size().checked_add(pad).ok_or(LayoutErr { private: () })?;
|
||||
let new_size = offset.checked_add(next.size()).ok_or(LayoutErr { private: () })?;
|
||||
|
||||
let layout = Layout::from_size_align(new_size, new_align)?;
|
||||
Ok((layout, offset))
|
||||
|
@ -312,8 +306,7 @@ impl Layout {
|
|||
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
|
||||
#[inline]
|
||||
pub fn extend_packed(&self, next: Self) -> Result<Self, LayoutErr> {
|
||||
let new_size = self.size().checked_add(next.size())
|
||||
.ok_or(LayoutErr { private: () })?;
|
||||
let new_size = self.size().checked_add(next.size()).ok_or(LayoutErr { private: () })?;
|
||||
Layout::from_size_align(new_size, self.align())
|
||||
}
|
||||
|
||||
|
@ -323,12 +316,10 @@ impl Layout {
|
|||
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
|
||||
#[inline]
|
||||
pub fn array<T>(n: usize) -> Result<Self, LayoutErr> {
|
||||
Layout::new::<T>()
|
||||
.repeat(n)
|
||||
.map(|(k, offs)| {
|
||||
debug_assert!(offs == mem::size_of::<T>());
|
||||
k
|
||||
})
|
||||
Layout::new::<T>().repeat(n).map(|(k, offs)| {
|
||||
debug_assert!(offs == mem::size_of::<T>());
|
||||
k
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -338,7 +329,7 @@ impl Layout {
|
|||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct LayoutErr {
|
||||
private: ()
|
||||
private: (),
|
||||
}
|
||||
|
||||
// (we need this for downstream impl of trait Error)
|
||||
|
@ -577,11 +568,7 @@ pub unsafe trait GlobalAlloc {
|
|||
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
|
||||
let new_ptr = self.alloc(new_layout);
|
||||
if !new_ptr.is_null() {
|
||||
ptr::copy_nonoverlapping(
|
||||
ptr,
|
||||
new_ptr,
|
||||
cmp::min(layout.size(), new_size),
|
||||
);
|
||||
ptr::copy_nonoverlapping(ptr, new_ptr, cmp::min(layout.size(), new_size));
|
||||
self.dealloc(ptr, layout);
|
||||
}
|
||||
new_ptr
|
||||
|
@ -669,7 +656,6 @@ pub unsafe trait GlobalAlloc {
|
|||
/// the future.
|
||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||
pub unsafe trait Alloc {
|
||||
|
||||
// (Note: some existing allocators have unspecified but well-defined
|
||||
// behavior in response to a zero size allocation request ;
|
||||
// e.g., in C, `malloc` of 0 will either return a null pointer or a
|
||||
|
@ -826,10 +812,12 @@ pub unsafe trait Alloc {
|
|||
/// rather than directly invoking `panic!` or similar.
|
||||
///
|
||||
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
|
||||
unsafe fn realloc(&mut self,
|
||||
ptr: NonNull<u8>,
|
||||
layout: Layout,
|
||||
new_size: usize) -> Result<NonNull<u8>, AllocErr> {
|
||||
unsafe fn realloc(
|
||||
&mut self,
|
||||
ptr: NonNull<u8>,
|
||||
layout: Layout,
|
||||
new_size: usize,
|
||||
) -> Result<NonNull<u8>, AllocErr> {
|
||||
let old_size = layout.size();
|
||||
|
||||
if new_size >= old_size {
|
||||
|
@ -846,9 +834,7 @@ pub unsafe trait Alloc {
|
|||
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
|
||||
let result = self.alloc(new_layout);
|
||||
if let Ok(new_ptr) = result {
|
||||
ptr::copy_nonoverlapping(ptr.as_ptr(),
|
||||
new_ptr.as_ptr(),
|
||||
cmp::min(old_size, new_size));
|
||||
ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), cmp::min(old_size, new_size));
|
||||
self.dealloc(ptr, layout);
|
||||
}
|
||||
result
|
||||
|
@ -924,14 +910,15 @@ pub unsafe trait Alloc {
|
|||
/// rather than directly invoking `panic!` or similar.
|
||||
///
|
||||
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
|
||||
unsafe fn realloc_excess(&mut self,
|
||||
ptr: NonNull<u8>,
|
||||
layout: Layout,
|
||||
new_size: usize) -> Result<Excess, AllocErr> {
|
||||
unsafe fn realloc_excess(
|
||||
&mut self,
|
||||
ptr: NonNull<u8>,
|
||||
layout: Layout,
|
||||
new_size: usize,
|
||||
) -> Result<Excess, AllocErr> {
|
||||
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
|
||||
let usable_size = self.usable_size(&new_layout);
|
||||
self.realloc(ptr, layout, new_size)
|
||||
.map(|p| Excess(p, usable_size.1))
|
||||
self.realloc(ptr, layout, new_size).map(|p| Excess(p, usable_size.1))
|
||||
}
|
||||
|
||||
/// Attempts to extend the allocation referenced by `ptr` to fit `new_size`.
|
||||
|
@ -969,20 +956,18 @@ pub unsafe trait Alloc {
|
|||
/// function; clients are expected either to be able to recover from
|
||||
/// `grow_in_place` failures without aborting, or to fall back on
|
||||
/// another reallocation method before resorting to an abort.
|
||||
unsafe fn grow_in_place(&mut self,
|
||||
ptr: NonNull<u8>,
|
||||
layout: Layout,
|
||||
new_size: usize) -> Result<(), CannotReallocInPlace> {
|
||||
unsafe fn grow_in_place(
|
||||
&mut self,
|
||||
ptr: NonNull<u8>,
|
||||
layout: Layout,
|
||||
new_size: usize,
|
||||
) -> Result<(), CannotReallocInPlace> {
|
||||
let _ = ptr; // this default implementation doesn't care about the actual address.
|
||||
debug_assert!(new_size >= layout.size());
|
||||
let (_l, u) = self.usable_size(&layout);
|
||||
// _l <= layout.size() [guaranteed by usable_size()]
|
||||
// layout.size() <= new_layout.size() [required by this method]
|
||||
if new_size <= u {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(CannotReallocInPlace)
|
||||
}
|
||||
if new_size <= u { Ok(()) } else { Err(CannotReallocInPlace) }
|
||||
}
|
||||
|
||||
/// Attempts to shrink the allocation referenced by `ptr` to fit `new_size`.
|
||||
|
@ -1024,23 +1009,20 @@ pub unsafe trait Alloc {
|
|||
/// function; clients are expected either to be able to recover from
|
||||
/// `shrink_in_place` failures without aborting, or to fall back
|
||||
/// on another reallocation method before resorting to an abort.
|
||||
unsafe fn shrink_in_place(&mut self,
|
||||
ptr: NonNull<u8>,
|
||||
layout: Layout,
|
||||
new_size: usize) -> Result<(), CannotReallocInPlace> {
|
||||
unsafe fn shrink_in_place(
|
||||
&mut self,
|
||||
ptr: NonNull<u8>,
|
||||
layout: Layout,
|
||||
new_size: usize,
|
||||
) -> Result<(), CannotReallocInPlace> {
|
||||
let _ = ptr; // this default implementation doesn't care about the actual address.
|
||||
debug_assert!(new_size <= layout.size());
|
||||
let (l, _u) = self.usable_size(&layout);
|
||||
// layout.size() <= _u [guaranteed by usable_size()]
|
||||
// new_layout.size() <= layout.size() [required by this method]
|
||||
if l <= new_size {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(CannotReallocInPlace)
|
||||
}
|
||||
if l <= new_size { Ok(()) } else { Err(CannotReallocInPlace) }
|
||||
}
|
||||
|
||||
|
||||
// == COMMON USAGE PATTERNS ==
|
||||
// alloc_one, dealloc_one, alloc_array, realloc_array. dealloc_array
|
||||
|
||||
|
@ -1074,14 +1056,11 @@ pub unsafe trait Alloc {
|
|||
///
|
||||
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
|
||||
fn alloc_one<T>(&mut self) -> Result<NonNull<T>, AllocErr>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let k = Layout::new::<T>();
|
||||
if k.size() > 0 {
|
||||
unsafe { self.alloc(k).map(|p| p.cast()) }
|
||||
} else {
|
||||
Err(AllocErr)
|
||||
}
|
||||
if k.size() > 0 { unsafe { self.alloc(k).map(|p| p.cast()) } } else { Err(AllocErr) }
|
||||
}
|
||||
|
||||
/// Deallocates a block suitable for holding an instance of `T`.
|
||||
|
@ -1102,7 +1081,8 @@ pub unsafe trait Alloc {
|
|||
///
|
||||
/// * the layout of `T` must *fit* that block of memory.
|
||||
unsafe fn dealloc_one<T>(&mut self, ptr: NonNull<T>)
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let k = Layout::new::<T>();
|
||||
if k.size() > 0 {
|
||||
|
@ -1143,14 +1123,11 @@ pub unsafe trait Alloc {
|
|||
///
|
||||
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
|
||||
fn alloc_array<T>(&mut self, n: usize) -> Result<NonNull<T>, AllocErr>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
match Layout::array::<T>(n) {
|
||||
Ok(layout) if layout.size() > 0 => {
|
||||
unsafe {
|
||||
self.alloc(layout).map(|p| p.cast())
|
||||
}
|
||||
}
|
||||
Ok(layout) if layout.size() > 0 => unsafe { self.alloc(layout).map(|p| p.cast()) },
|
||||
_ => Err(AllocErr),
|
||||
}
|
||||
}
|
||||
|
@ -1189,20 +1166,21 @@ pub unsafe trait Alloc {
|
|||
/// rather than directly invoking `panic!` or similar.
|
||||
///
|
||||
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
|
||||
unsafe fn realloc_array<T>(&mut self,
|
||||
ptr: NonNull<T>,
|
||||
n_old: usize,
|
||||
n_new: usize) -> Result<NonNull<T>, AllocErr>
|
||||
where Self: Sized
|
||||
unsafe fn realloc_array<T>(
|
||||
&mut self,
|
||||
ptr: NonNull<T>,
|
||||
n_old: usize,
|
||||
n_new: usize,
|
||||
) -> Result<NonNull<T>, AllocErr>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
match (Layout::array::<T>(n_old), Layout::array::<T>(n_new)) {
|
||||
(Ok(k_old), Ok(k_new)) if k_old.size() > 0 && k_new.size() > 0 => {
|
||||
debug_assert!(k_old.align() == k_new.align());
|
||||
self.realloc(ptr.cast(), k_old, k_new.size()).map(NonNull::cast)
|
||||
}
|
||||
_ => {
|
||||
Err(AllocErr)
|
||||
}
|
||||
_ => Err(AllocErr),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1227,15 +1205,12 @@ pub unsafe trait Alloc {
|
|||
///
|
||||
/// Always returns `Err` on arithmetic overflow.
|
||||
unsafe fn dealloc_array<T>(&mut self, ptr: NonNull<T>, n: usize) -> Result<(), AllocErr>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
match Layout::array::<T>(n) {
|
||||
Ok(k) if k.size() > 0 => {
|
||||
Ok(self.dealloc(ptr.cast(), k))
|
||||
}
|
||||
_ => {
|
||||
Err(AllocErr)
|
||||
}
|
||||
Ok(k) if k.size() > 0 => Ok(self.dealloc(ptr.cast(), k)),
|
||||
_ => Err(AllocErr),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,8 +105,10 @@ pub trait Any: 'static {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: 'static + ?Sized > Any for T {
|
||||
fn type_id(&self) -> TypeId { TypeId::of::<T>() }
|
||||
impl<T: 'static + ?Sized> Any for T {
|
||||
fn type_id(&self) -> TypeId {
|
||||
TypeId::of::<T>()
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -193,9 +195,7 @@ impl dyn Any {
|
|||
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
|
||||
if self.is::<T>() {
|
||||
// SAFETY: just checked whether we are pointing to the correct type
|
||||
unsafe {
|
||||
Some(&*(self as *const dyn Any as *const T))
|
||||
}
|
||||
unsafe { Some(&*(self as *const dyn Any as *const T)) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -229,16 +229,14 @@ impl dyn Any {
|
|||
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
|
||||
if self.is::<T>() {
|
||||
// SAFETY: just checked whether we are pointing to the correct type
|
||||
unsafe {
|
||||
Some(&mut *(self as *mut dyn Any as *mut T))
|
||||
}
|
||||
unsafe { Some(&mut *(self as *mut dyn Any as *mut T)) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn Any+Send {
|
||||
impl dyn Any + Send {
|
||||
/// Forwards to the method defined on the type `Any`.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -316,7 +314,7 @@ impl dyn Any+Send {
|
|||
}
|
||||
}
|
||||
|
||||
impl dyn Any+Send+Sync {
|
||||
impl dyn Any + Send + Sync {
|
||||
/// Forwards to the method defined on the type `Any`.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -433,11 +431,9 @@ impl TypeId {
|
|||
/// assert_eq!(is_string(&"cookie monster".to_string()), true);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature="const_type_id", issue = "41875")]
|
||||
#[rustc_const_unstable(feature = "const_type_id", issue = "41875")]
|
||||
pub const fn of<T: ?Sized + 'static>() -> TypeId {
|
||||
TypeId {
|
||||
t: intrinsics::type_id::<T>(),
|
||||
}
|
||||
TypeId { t: intrinsics::type_id::<T>() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! Defines the `IntoIter` owned iterator for arrays.
|
||||
|
||||
use super::LengthAtMost32;
|
||||
use crate::{
|
||||
fmt,
|
||||
iter::{ExactSizeIterator, FusedIterator, TrustedLen},
|
||||
|
@ -7,8 +8,6 @@ use crate::{
|
|||
ops::Range,
|
||||
ptr,
|
||||
};
|
||||
use super::LengthAtMost32;
|
||||
|
||||
|
||||
/// A by-value [array] iterator.
|
||||
///
|
||||
|
@ -40,7 +39,7 @@ where
|
|||
alive: Range<usize>,
|
||||
}
|
||||
|
||||
impl<T, const N: usize> IntoIter<T, {N}>
|
||||
impl<T, const N: usize> IntoIter<T, { N }>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
|
@ -75,10 +74,7 @@ where
|
|||
data
|
||||
};
|
||||
|
||||
Self {
|
||||
data,
|
||||
alive: 0..N,
|
||||
}
|
||||
Self { data, alive: 0..N }
|
||||
}
|
||||
|
||||
/// Returns an immutable slice of all elements that have not been yielded
|
||||
|
@ -88,9 +84,7 @@ where
|
|||
// SAFETY: This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
|
||||
// the size and alignment of `T`. Furthermore, we know that all
|
||||
// elements within `alive` are properly initialized.
|
||||
unsafe {
|
||||
mem::transmute::<&[MaybeUninit<T>], &[T]>(slice)
|
||||
}
|
||||
unsafe { mem::transmute::<&[MaybeUninit<T>], &[T]>(slice) }
|
||||
}
|
||||
|
||||
/// Returns a mutable slice of all elements that have not been yielded yet.
|
||||
|
@ -100,15 +94,12 @@ where
|
|||
// SAFETY: This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
|
||||
// the size and alignment of `T`. Furthermore, we know that all
|
||||
// elements within `alive` are properly initialized.
|
||||
unsafe {
|
||||
mem::transmute::<&mut [MaybeUninit<T>], &mut [T]>(slice)
|
||||
}
|
||||
unsafe { mem::transmute::<&mut [MaybeUninit<T>], &mut [T]>(slice) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T, const N: usize> Iterator for IntoIter<T, {N}>
|
||||
impl<T, const N: usize> Iterator for IntoIter<T, { N }>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
|
@ -155,7 +146,7 @@ where
|
|||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, {N}>
|
||||
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, { N }>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
|
@ -191,7 +182,7 @@ where
|
|||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T, const N: usize> Drop for IntoIter<T, {N}>
|
||||
impl<T, const N: usize> Drop for IntoIter<T, { N }>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
|
@ -199,14 +190,12 @@ where
|
|||
// SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice
|
||||
// of elements that have not been moved out yet and that remain
|
||||
// to be dropped.
|
||||
unsafe {
|
||||
ptr::drop_in_place(self.as_mut_slice())
|
||||
}
|
||||
unsafe { ptr::drop_in_place(self.as_mut_slice()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, {N}>
|
||||
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, { N }>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
|
@ -221,23 +210,17 @@ where
|
|||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T, const N: usize> FusedIterator for IntoIter<T, {N}>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{}
|
||||
impl<T, const N: usize> FusedIterator for IntoIter<T, { N }> where [T; N]: LengthAtMost32 {}
|
||||
|
||||
// The iterator indeed reports the correct length. The number of "alive"
|
||||
// elements (that will still be yielded) is the length of the range `alive`.
|
||||
// This range is decremented in length in either `next` or `next_back`. It is
|
||||
// always decremented by 1 in those methods, but only if `Some(_)` is returned.
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, {N}>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{}
|
||||
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, { N }> where [T; N]: LengthAtMost32 {}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T: Clone, const N: usize> Clone for IntoIter<T, {N}>
|
||||
impl<T: Clone, const N: usize> Clone for IntoIter<T, { N }>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
|
@ -260,24 +243,19 @@ where
|
|||
new_data.get_unchecked_mut(idx).write(clone);
|
||||
}
|
||||
|
||||
Self {
|
||||
data: new_data,
|
||||
alive: self.alive.clone(),
|
||||
}
|
||||
Self { data: new_data, alive: self.alive.clone() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, {N}>
|
||||
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, { N }>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// Only print the elements that were not yielded yet: we cannot
|
||||
// access the yielded elements anymore.
|
||||
f.debug_tuple("IntoIter")
|
||||
.field(&self.as_slice())
|
||||
.finish()
|
||||
f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::borrow::{Borrow, BorrowMut};
|
|||
use crate::cmp::Ordering;
|
||||
use crate::convert::{Infallible, TryFrom};
|
||||
use crate::fmt;
|
||||
use crate::hash::{Hash, self};
|
||||
use crate::hash::{self, Hash};
|
||||
use crate::marker::Unsize;
|
||||
use crate::slice::{Iter, IterMut};
|
||||
|
||||
|
@ -71,10 +71,12 @@ impl fmt::Display for TryFromSliceError {
|
|||
}
|
||||
|
||||
impl TryFromSliceError {
|
||||
#[unstable(feature = "array_error_internals",
|
||||
reason = "available through Error trait and this method should not \
|
||||
#[unstable(
|
||||
feature = "array_error_internals",
|
||||
reason = "available through Error trait and this method should not \
|
||||
be exposed publicly",
|
||||
issue = "none")]
|
||||
issue = "none"
|
||||
)]
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
pub fn __description(&self) -> &str {
|
||||
|
@ -385,11 +387,12 @@ where
|
|||
}
|
||||
|
||||
/// Implemented for lengths where trait impls are allowed on arrays in core/std
|
||||
#[rustc_on_unimplemented(
|
||||
message="arrays only have std trait implementations for lengths 0..=32",
|
||||
#[rustc_on_unimplemented(message = "arrays only have std trait implementations for lengths 0..=32")]
|
||||
#[unstable(
|
||||
feature = "const_generic_impls_guard",
|
||||
issue = "none",
|
||||
reason = "will never be stable, just a temporary step until const generics are stable"
|
||||
)]
|
||||
#[unstable(feature = "const_generic_impls_guard", issue = "none",
|
||||
reason = "will never be stable, just a temporary step until const generics are stable")]
|
||||
pub trait LengthAtMost32 {}
|
||||
|
||||
macro_rules! array_impls {
|
||||
|
@ -429,4 +432,4 @@ macro_rules! array_impl_default {
|
|||
};
|
||||
}
|
||||
|
||||
array_impl_default!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
|
||||
array_impl_default! {32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
|
||||
|
|
|
@ -21,7 +21,6 @@ fn starts_with_str(b: &mut Bencher) {
|
|||
})
|
||||
}
|
||||
|
||||
|
||||
#[bench]
|
||||
fn ends_with_char(b: &mut Bencher) {
|
||||
let text = black_box("kdjsfhlakfhlsghlkvcnljknfqiunvcijqenwodind");
|
||||
|
|
|
@ -189,7 +189,7 @@ pub trait Borrow<Borrowed: ?Sized> {
|
|||
///
|
||||
/// [`Borrow<T>`]: trait.Borrow.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
|
||||
pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
|
||||
/// Mutably borrows from an owned value.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -211,25 +211,35 @@ pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
|
|||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Borrow<T> for T {
|
||||
fn borrow(&self) -> &T { self }
|
||||
fn borrow(&self) -> &T {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> BorrowMut<T> for T {
|
||||
fn borrow_mut(&mut self) -> &mut T { self }
|
||||
fn borrow_mut(&mut self) -> &mut T {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Borrow<T> for &T {
|
||||
fn borrow(&self) -> &T { &**self }
|
||||
fn borrow(&self) -> &T {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Borrow<T> for &mut T {
|
||||
fn borrow(&self) -> &T { &**self }
|
||||
fn borrow(&self) -> &T {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> BorrowMut<T> for &mut T {
|
||||
fn borrow_mut(&mut self) -> &mut T { &mut **self }
|
||||
fn borrow_mut(&mut self) -> &mut T {
|
||||
&mut **self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ use crate::cmp::Ordering;
|
|||
use crate::fmt::{self, Debug, Display};
|
||||
use crate::marker::Unsize;
|
||||
use crate::mem;
|
||||
use crate::ops::{Deref, DerefMut, CoerceUnsized};
|
||||
use crate::ops::{CoerceUnsized, Deref, DerefMut};
|
||||
use crate::ptr;
|
||||
|
||||
/// A mutable memory location.
|
||||
|
@ -243,7 +243,7 @@ unsafe impl<T: ?Sized> Send for Cell<T> where T: Send {}
|
|||
impl<T: ?Sized> !Sync for Cell<T> {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T:Copy> Clone for Cell<T> {
|
||||
impl<T: Copy> Clone for Cell<T> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Cell<T> {
|
||||
Cell::new(self.get())
|
||||
|
@ -327,9 +327,7 @@ impl<T> Cell<T> {
|
|||
#[rustc_const_stable(feature = "const_cell_new", since = "1.32.0")]
|
||||
#[inline]
|
||||
pub const fn new(value: T) -> Cell<T> {
|
||||
Cell {
|
||||
value: UnsafeCell::new(value),
|
||||
}
|
||||
Cell { value: UnsafeCell::new(value) }
|
||||
}
|
||||
|
||||
/// Sets the contained value.
|
||||
|
@ -410,7 +408,7 @@ impl<T> Cell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T:Copy> Cell<T> {
|
||||
impl<T: Copy> Cell<T> {
|
||||
/// Returns a copy of the contained value.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -425,7 +423,7 @@ impl<T:Copy> Cell<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get(&self) -> T {
|
||||
unsafe{ *self.value.get() }
|
||||
unsafe { *self.value.get() }
|
||||
}
|
||||
|
||||
/// Updates the contained value using a function and returns the new value.
|
||||
|
@ -493,9 +491,7 @@ impl<T: ?Sized> Cell<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "cell_get_mut", since = "1.11.0")]
|
||||
pub fn get_mut(&mut self) -> &mut T {
|
||||
unsafe {
|
||||
&mut *self.value.get()
|
||||
}
|
||||
unsafe { &mut *self.value.get() }
|
||||
}
|
||||
|
||||
/// Returns a `&Cell<T>` from a `&mut T`
|
||||
|
@ -514,9 +510,7 @@ impl<T: ?Sized> Cell<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "as_cell", since = "1.37.0")]
|
||||
pub fn from_mut(t: &mut T) -> &Cell<T> {
|
||||
unsafe {
|
||||
&*(t as *mut T as *const Cell<T>)
|
||||
}
|
||||
unsafe { &*(t as *mut T as *const Cell<T>) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -559,9 +553,7 @@ impl<T> Cell<[T]> {
|
|||
/// ```
|
||||
#[stable(feature = "as_cell", since = "1.37.0")]
|
||||
pub fn as_slice_of_cells(&self) -> &[Cell<T>] {
|
||||
unsafe {
|
||||
&*(self as *const Cell<[T]> as *const [Cell<T>])
|
||||
}
|
||||
unsafe { &*(self as *const Cell<[T]> as *const [Cell<T>]) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -654,10 +646,7 @@ impl<T> RefCell<T> {
|
|||
#[rustc_const_stable(feature = "const_refcell_new", since = "1.32.0")]
|
||||
#[inline]
|
||||
pub const fn new(value: T) -> RefCell<T> {
|
||||
RefCell {
|
||||
value: UnsafeCell::new(value),
|
||||
borrow: Cell::new(UNUSED),
|
||||
}
|
||||
RefCell { value: UnsafeCell::new(value), borrow: Cell::new(UNUSED) }
|
||||
}
|
||||
|
||||
/// Consumes the `RefCell`, returning the wrapped value.
|
||||
|
@ -700,7 +689,7 @@ impl<T> RefCell<T> {
|
|||
/// assert_eq!(cell, RefCell::new(6));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "refcell_replace", since="1.24.0")]
|
||||
#[stable(feature = "refcell_replace", since = "1.24.0")]
|
||||
pub fn replace(&self, t: T) -> T {
|
||||
mem::replace(&mut *self.borrow_mut(), t)
|
||||
}
|
||||
|
@ -722,7 +711,7 @@ impl<T> RefCell<T> {
|
|||
/// assert_eq!(cell, RefCell::new(6));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "refcell_replace_swap", since="1.35.0")]
|
||||
#[stable(feature = "refcell_replace_swap", since = "1.35.0")]
|
||||
pub fn replace_with<F: FnOnce(&mut T) -> T>(&self, f: F) -> T {
|
||||
let mut_borrow = &mut *self.borrow_mut();
|
||||
let replacement = f(mut_borrow);
|
||||
|
@ -749,7 +738,7 @@ impl<T> RefCell<T> {
|
|||
/// assert_eq!(d, RefCell::new(5));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "refcell_swap", since="1.24.0")]
|
||||
#[stable(feature = "refcell_swap", since = "1.24.0")]
|
||||
pub fn swap(&self, other: &Self) {
|
||||
mem::swap(&mut *self.borrow_mut(), &mut *other.borrow_mut())
|
||||
}
|
||||
|
@ -827,10 +816,7 @@ impl<T: ?Sized> RefCell<T> {
|
|||
#[inline]
|
||||
pub fn try_borrow(&self) -> Result<Ref<'_, T>, BorrowError> {
|
||||
match BorrowRef::new(&self.borrow) {
|
||||
Some(b) => Ok(Ref {
|
||||
value: unsafe { &*self.value.get() },
|
||||
borrow: b,
|
||||
}),
|
||||
Some(b) => Ok(Ref { value: unsafe { &*self.value.get() }, borrow: b }),
|
||||
None => Err(BorrowError { _private: () }),
|
||||
}
|
||||
}
|
||||
|
@ -905,10 +891,7 @@ impl<T: ?Sized> RefCell<T> {
|
|||
#[inline]
|
||||
pub fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, BorrowMutError> {
|
||||
match BorrowRefMut::new(&self.borrow) {
|
||||
Some(b) => Ok(RefMut {
|
||||
value: unsafe { &mut *self.value.get() },
|
||||
borrow: b,
|
||||
}),
|
||||
Some(b) => Ok(RefMut { value: unsafe { &mut *self.value.get() }, borrow: b }),
|
||||
None => Err(BorrowMutError { _private: () }),
|
||||
}
|
||||
}
|
||||
|
@ -957,9 +940,7 @@ impl<T: ?Sized> RefCell<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "cell_get_mut", since = "1.11.0")]
|
||||
pub fn get_mut(&mut self) -> &mut T {
|
||||
unsafe {
|
||||
&mut *self.value.get()
|
||||
}
|
||||
unsafe { &mut *self.value.get() }
|
||||
}
|
||||
|
||||
/// Immutably borrows the wrapped value, returning an error if the value is
|
||||
|
@ -1189,10 +1170,7 @@ impl<'b, T: ?Sized> Ref<'b, T> {
|
|||
#[stable(feature = "cell_extras", since = "1.15.0")]
|
||||
#[inline]
|
||||
pub fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> {
|
||||
Ref {
|
||||
value: orig.value,
|
||||
borrow: orig.borrow.clone(),
|
||||
}
|
||||
Ref { value: orig.value, borrow: orig.borrow.clone() }
|
||||
}
|
||||
|
||||
/// Makes a new `Ref` for a component of the borrowed data.
|
||||
|
@ -1216,12 +1194,10 @@ impl<'b, T: ?Sized> Ref<'b, T> {
|
|||
#[stable(feature = "cell_map", since = "1.8.0")]
|
||||
#[inline]
|
||||
pub fn map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Ref<'b, U>
|
||||
where F: FnOnce(&T) -> &U
|
||||
where
|
||||
F: FnOnce(&T) -> &U,
|
||||
{
|
||||
Ref {
|
||||
value: f(orig.value),
|
||||
borrow: orig.borrow,
|
||||
}
|
||||
Ref { value: f(orig.value), borrow: orig.borrow }
|
||||
}
|
||||
|
||||
/// Splits a `Ref` into multiple `Ref`s for different components of the
|
||||
|
@ -1247,7 +1223,8 @@ impl<'b, T: ?Sized> Ref<'b, T> {
|
|||
#[stable(feature = "refcell_map_split", since = "1.35.0")]
|
||||
#[inline]
|
||||
pub fn map_split<U: ?Sized, V: ?Sized, F>(orig: Ref<'b, T>, f: F) -> (Ref<'b, U>, Ref<'b, V>)
|
||||
where F: FnOnce(&T) -> (&U, &V)
|
||||
where
|
||||
F: FnOnce(&T) -> (&U, &V),
|
||||
{
|
||||
let (a, b) = f(orig.value);
|
||||
let borrow = orig.borrow.clone();
|
||||
|
@ -1292,14 +1269,12 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
|
|||
#[stable(feature = "cell_map", since = "1.8.0")]
|
||||
#[inline]
|
||||
pub fn map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> RefMut<'b, U>
|
||||
where F: FnOnce(&mut T) -> &mut U
|
||||
where
|
||||
F: FnOnce(&mut T) -> &mut U,
|
||||
{
|
||||
// FIXME(nll-rfc#40): fix borrow-check
|
||||
let RefMut { value, borrow } = orig;
|
||||
RefMut {
|
||||
value: f(value),
|
||||
borrow,
|
||||
}
|
||||
RefMut { value: f(value), borrow }
|
||||
}
|
||||
|
||||
/// Splits a `RefMut` into multiple `RefMut`s for different components of the
|
||||
|
@ -1330,9 +1305,11 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
|
|||
#[stable(feature = "refcell_map_split", since = "1.35.0")]
|
||||
#[inline]
|
||||
pub fn map_split<U: ?Sized, V: ?Sized, F>(
|
||||
orig: RefMut<'b, T>, f: F
|
||||
orig: RefMut<'b, T>,
|
||||
f: F,
|
||||
) -> (RefMut<'b, U>, RefMut<'b, V>)
|
||||
where F: FnOnce(&mut T) -> (&mut U, &mut V)
|
||||
where
|
||||
F: FnOnce(&mut T) -> (&mut U, &mut V),
|
||||
{
|
||||
let (a, b) = f(orig.value);
|
||||
let borrow = orig.borrow.clone();
|
||||
|
@ -1364,7 +1341,7 @@ impl<'b> BorrowRefMut<'b> {
|
|||
UNUSED => {
|
||||
borrow.set(UNUSED - 1);
|
||||
Some(BorrowRefMut { borrow })
|
||||
},
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,8 +195,8 @@ use self::Ordering::*;
|
|||
#[doc(alias = "==")]
|
||||
#[doc(alias = "!=")]
|
||||
#[rustc_on_unimplemented(
|
||||
message="can't compare `{Self}` with `{Rhs}`",
|
||||
label="no implementation for `{Self} == {Rhs}`",
|
||||
message = "can't compare `{Self}` with `{Rhs}`",
|
||||
label = "no implementation for `{Self} == {Rhs}`"
|
||||
)]
|
||||
pub trait PartialEq<Rhs: ?Sized = Self> {
|
||||
/// This method tests for `self` and `other` values to be equal, and is used
|
||||
|
@ -209,14 +209,18 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
|
|||
#[inline]
|
||||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn ne(&self, other: &Rhs) -> bool { !self.eq(other) }
|
||||
fn ne(&self, other: &Rhs) -> bool {
|
||||
!self.eq(other)
|
||||
}
|
||||
}
|
||||
|
||||
/// Derive macro generating an impl of the trait `PartialEq`.
|
||||
#[rustc_builtin_macro]
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
#[allow_internal_unstable(core_intrinsics, structural_match)]
|
||||
pub macro PartialEq($item:item) { /* compiler built-in */ }
|
||||
pub macro PartialEq($item:item) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
/// Trait for equality comparisons which are [equivalence relations](
|
||||
/// https://en.wikipedia.org/wiki/Equivalence_relation).
|
||||
|
@ -278,7 +282,9 @@ pub trait Eq: PartialEq<Self> {
|
|||
#[rustc_builtin_macro]
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
#[allow_internal_unstable(core_intrinsics, derive_eq, structural_match)]
|
||||
pub macro Eq($item:item) { /* compiler built-in */ }
|
||||
pub macro Eq($item:item) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
// FIXME: this struct is used solely by #[derive] to
|
||||
// assert that every component of a type implements Eq.
|
||||
|
@ -286,10 +292,10 @@ pub macro Eq($item:item) { /* compiler built-in */ }
|
|||
// This struct should never appear in user code.
|
||||
#[doc(hidden)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[unstable(feature = "derive_eq",
|
||||
reason = "deriving hack, should not be public",
|
||||
issue = "none")]
|
||||
pub struct AssertParamIsEq<T: Eq + ?Sized> { _field: crate::marker::PhantomData<T> }
|
||||
#[unstable(feature = "derive_eq", reason = "deriving hack, should not be public", issue = "none")]
|
||||
pub struct AssertParamIsEq<T: Eq + ?Sized> {
|
||||
_field: crate::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
/// An `Ordering` is the result of a comparison between two values.
|
||||
///
|
||||
|
@ -460,13 +466,21 @@ impl<T: PartialOrd> PartialOrd for Reverse<T> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn lt(&self, other: &Self) -> bool { other.0 < self.0 }
|
||||
fn lt(&self, other: &Self) -> bool {
|
||||
other.0 < self.0
|
||||
}
|
||||
#[inline]
|
||||
fn le(&self, other: &Self) -> bool { other.0 <= self.0 }
|
||||
fn le(&self, other: &Self) -> bool {
|
||||
other.0 <= self.0
|
||||
}
|
||||
#[inline]
|
||||
fn gt(&self, other: &Self) -> bool { other.0 > self.0 }
|
||||
fn gt(&self, other: &Self) -> bool {
|
||||
other.0 > self.0
|
||||
}
|
||||
#[inline]
|
||||
fn ge(&self, other: &Self) -> bool { other.0 >= self.0 }
|
||||
fn ge(&self, other: &Self) -> bool {
|
||||
other.0 >= self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
|
||||
|
@ -570,7 +584,9 @@ pub trait Ord: Eq + PartialOrd<Self> {
|
|||
#[stable(feature = "ord_max_min", since = "1.21.0")]
|
||||
#[inline]
|
||||
fn max(self, other: Self) -> Self
|
||||
where Self: Sized {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
max_by(self, other, Ord::cmp)
|
||||
}
|
||||
|
||||
|
@ -587,7 +603,9 @@ pub trait Ord: Eq + PartialOrd<Self> {
|
|||
#[stable(feature = "ord_max_min", since = "1.21.0")]
|
||||
#[inline]
|
||||
fn min(self, other: Self) -> Self
|
||||
where Self: Sized {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
min_by(self, other, Ord::cmp)
|
||||
}
|
||||
|
||||
|
@ -611,7 +629,9 @@ pub trait Ord: Eq + PartialOrd<Self> {
|
|||
/// ```
|
||||
#[unstable(feature = "clamp", issue = "44095")]
|
||||
fn clamp(self, min: Self, max: Self) -> Self
|
||||
where Self: Sized {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
assert!(min <= max);
|
||||
if self < min {
|
||||
min
|
||||
|
@ -627,7 +647,9 @@ pub trait Ord: Eq + PartialOrd<Self> {
|
|||
#[rustc_builtin_macro]
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
#[allow_internal_unstable(core_intrinsics)]
|
||||
pub macro Ord($item:item) { /* compiler built-in */ }
|
||||
pub macro Ord($item:item) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Eq for Ordering {}
|
||||
|
@ -753,8 +775,8 @@ impl PartialOrd for Ordering {
|
|||
#[doc(alias = "<=")]
|
||||
#[doc(alias = ">=")]
|
||||
#[rustc_on_unimplemented(
|
||||
message="can't compare `{Self}` with `{Rhs}`",
|
||||
label="no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`",
|
||||
message = "can't compare `{Self}` with `{Rhs}`",
|
||||
label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`"
|
||||
)]
|
||||
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
||||
/// This method returns an ordering between `self` and `other` values if one exists.
|
||||
|
@ -875,7 +897,9 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
|||
#[rustc_builtin_macro]
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
#[allow_internal_unstable(core_intrinsics)]
|
||||
pub macro PartialOrd($item:item) { /* compiler built-in */ }
|
||||
pub macro PartialOrd($item:item) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
/// Compares and returns the minimum of two values.
|
||||
///
|
||||
|
@ -1005,8 +1029,8 @@ pub fn max_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
|
|||
|
||||
// Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types
|
||||
mod impls {
|
||||
use crate::cmp::Ordering::{self, Equal, Greater, Less};
|
||||
use crate::hint::unreachable_unchecked;
|
||||
use crate::cmp::Ordering::{self, Less, Greater, Equal};
|
||||
|
||||
macro_rules! partial_eq_impl {
|
||||
($($t:ty)*) => ($(
|
||||
|
@ -1023,9 +1047,13 @@ mod impls {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl PartialEq for () {
|
||||
#[inline]
|
||||
fn eq(&self, _other: &()) -> bool { true }
|
||||
fn eq(&self, _other: &()) -> bool {
|
||||
true
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, _other: &()) -> bool { false }
|
||||
fn ne(&self, _other: &()) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
partial_eq_impl! {
|
||||
|
@ -1119,7 +1147,9 @@ mod impls {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Ord for () {
|
||||
#[inline]
|
||||
fn cmp(&self, _other: &()) -> Ordering { Equal }
|
||||
fn cmp(&self, _other: &()) -> Ordering {
|
||||
Equal
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -1168,31 +1198,54 @@ mod impls {
|
|||
// & pointers
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &A where A: PartialEq<B> {
|
||||
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &A
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: & &B) -> bool { PartialEq::eq(*self, *other) }
|
||||
fn eq(&self, other: &&B) -> bool {
|
||||
PartialEq::eq(*self, *other)
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: & &B) -> bool { PartialEq::ne(*self, *other) }
|
||||
fn ne(&self, other: &&B) -> bool {
|
||||
PartialEq::ne(*self, *other)
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized, B: ?Sized> PartialOrd<&B> for &A where A: PartialOrd<B> {
|
||||
impl<A: ?Sized, B: ?Sized> PartialOrd<&B> for &A
|
||||
where
|
||||
A: PartialOrd<B>,
|
||||
{
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &&B) -> Option<Ordering> {
|
||||
PartialOrd::partial_cmp(*self, *other)
|
||||
}
|
||||
#[inline]
|
||||
fn lt(&self, other: & &B) -> bool { PartialOrd::lt(*self, *other) }
|
||||
fn lt(&self, other: &&B) -> bool {
|
||||
PartialOrd::lt(*self, *other)
|
||||
}
|
||||
#[inline]
|
||||
fn le(&self, other: & &B) -> bool { PartialOrd::le(*self, *other) }
|
||||
fn le(&self, other: &&B) -> bool {
|
||||
PartialOrd::le(*self, *other)
|
||||
}
|
||||
#[inline]
|
||||
fn gt(&self, other: & &B) -> bool { PartialOrd::gt(*self, *other) }
|
||||
fn gt(&self, other: &&B) -> bool {
|
||||
PartialOrd::gt(*self, *other)
|
||||
}
|
||||
#[inline]
|
||||
fn ge(&self, other: & &B) -> bool { PartialOrd::ge(*self, *other) }
|
||||
fn ge(&self, other: &&B) -> bool {
|
||||
PartialOrd::ge(*self, *other)
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized> Ord for &A where A: Ord {
|
||||
impl<A: ?Sized> Ord for &A
|
||||
where
|
||||
A: Ord,
|
||||
{
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Self) -> Ordering { Ord::cmp(*self, *other) }
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
Ord::cmp(*self, *other)
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized> Eq for &A where A: Eq {}
|
||||
|
@ -1200,48 +1253,85 @@ mod impls {
|
|||
// &mut pointers
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &mut A where A: PartialEq<B> {
|
||||
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &mut A
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &&mut B) -> bool { PartialEq::eq(*self, *other) }
|
||||
fn eq(&self, other: &&mut B) -> bool {
|
||||
PartialEq::eq(*self, *other)
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &&mut B) -> bool { PartialEq::ne(*self, *other) }
|
||||
fn ne(&self, other: &&mut B) -> bool {
|
||||
PartialEq::ne(*self, *other)
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized, B: ?Sized> PartialOrd<&mut B> for &mut A where A: PartialOrd<B> {
|
||||
impl<A: ?Sized, B: ?Sized> PartialOrd<&mut B> for &mut A
|
||||
where
|
||||
A: PartialOrd<B>,
|
||||
{
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &&mut B) -> Option<Ordering> {
|
||||
PartialOrd::partial_cmp(*self, *other)
|
||||
}
|
||||
#[inline]
|
||||
fn lt(&self, other: &&mut B) -> bool { PartialOrd::lt(*self, *other) }
|
||||
fn lt(&self, other: &&mut B) -> bool {
|
||||
PartialOrd::lt(*self, *other)
|
||||
}
|
||||
#[inline]
|
||||
fn le(&self, other: &&mut B) -> bool { PartialOrd::le(*self, *other) }
|
||||
fn le(&self, other: &&mut B) -> bool {
|
||||
PartialOrd::le(*self, *other)
|
||||
}
|
||||
#[inline]
|
||||
fn gt(&self, other: &&mut B) -> bool { PartialOrd::gt(*self, *other) }
|
||||
fn gt(&self, other: &&mut B) -> bool {
|
||||
PartialOrd::gt(*self, *other)
|
||||
}
|
||||
#[inline]
|
||||
fn ge(&self, other: &&mut B) -> bool { PartialOrd::ge(*self, *other) }
|
||||
fn ge(&self, other: &&mut B) -> bool {
|
||||
PartialOrd::ge(*self, *other)
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized> Ord for &mut A where A: Ord {
|
||||
impl<A: ?Sized> Ord for &mut A
|
||||
where
|
||||
A: Ord,
|
||||
{
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Self) -> Ordering { Ord::cmp(*self, *other) }
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
Ord::cmp(*self, *other)
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized> Eq for &mut A where A: Eq {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &A where A: PartialEq<B> {
|
||||
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &A
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &&mut B) -> bool { PartialEq::eq(*self, *other) }
|
||||
fn eq(&self, other: &&mut B) -> bool {
|
||||
PartialEq::eq(*self, *other)
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &&mut B) -> bool { PartialEq::ne(*self, *other) }
|
||||
fn ne(&self, other: &&mut B) -> bool {
|
||||
PartialEq::ne(*self, *other)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &mut A where A: PartialEq<B> {
|
||||
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &mut A
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &&B) -> bool { PartialEq::eq(*self, *other) }
|
||||
fn eq(&self, other: &&B) -> bool {
|
||||
PartialEq::eq(*self, *other)
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &&B) -> bool { PartialEq::ne(*self, *other) }
|
||||
fn ne(&self, other: &&B) -> bool {
|
||||
PartialEq::ne(*self, *other)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,21 +11,18 @@ struct PadAdapterState {
|
|||
|
||||
impl Default for PadAdapterState {
|
||||
fn default() -> Self {
|
||||
PadAdapterState {
|
||||
on_newline: true,
|
||||
}
|
||||
PadAdapterState { on_newline: true }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'buf, 'state> PadAdapter<'buf, 'state> {
|
||||
fn wrap<'slot, 'fmt: 'buf+'slot>(fmt: &'fmt mut fmt::Formatter<'_>,
|
||||
slot: &'slot mut Option<Self>,
|
||||
state: &'state mut PadAdapterState) -> fmt::Formatter<'slot> {
|
||||
fn wrap<'slot, 'fmt: 'buf + 'slot>(
|
||||
fmt: &'fmt mut fmt::Formatter<'_>,
|
||||
slot: &'slot mut Option<Self>,
|
||||
state: &'state mut PadAdapterState,
|
||||
) -> fmt::Formatter<'slot> {
|
||||
fmt.wrap_buf(move |buf| {
|
||||
*slot = Some(PadAdapter {
|
||||
buf,
|
||||
state,
|
||||
});
|
||||
*slot = Some(PadAdapter { buf, state });
|
||||
slot.as_mut().unwrap()
|
||||
})
|
||||
}
|
||||
|
@ -98,15 +95,12 @@ pub struct DebugStruct<'a, 'b: 'a> {
|
|||
has_fields: bool,
|
||||
}
|
||||
|
||||
pub(super) fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>,
|
||||
name: &str)
|
||||
-> DebugStruct<'a, 'b> {
|
||||
pub(super) fn debug_struct_new<'a, 'b>(
|
||||
fmt: &'a mut fmt::Formatter<'b>,
|
||||
name: &str,
|
||||
) -> DebugStruct<'a, 'b> {
|
||||
let result = fmt.write_str(name);
|
||||
DebugStruct {
|
||||
fmt,
|
||||
result,
|
||||
has_fields: false,
|
||||
}
|
||||
DebugStruct { fmt, result, has_fields: false }
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
|
||||
|
@ -196,11 +190,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
|
|||
pub fn finish(&mut self) -> fmt::Result {
|
||||
if self.has_fields {
|
||||
self.result = self.result.and_then(|_| {
|
||||
if self.is_pretty() {
|
||||
self.fmt.write_str("}")
|
||||
} else {
|
||||
self.fmt.write_str(" }")
|
||||
}
|
||||
if self.is_pretty() { self.fmt.write_str("}") } else { self.fmt.write_str(" }") }
|
||||
});
|
||||
}
|
||||
self.result
|
||||
|
@ -256,12 +246,7 @@ pub(super) fn debug_tuple_new<'a, 'b>(
|
|||
name: &str,
|
||||
) -> DebugTuple<'a, 'b> {
|
||||
let result = fmt.write_str(name);
|
||||
DebugTuple {
|
||||
fmt,
|
||||
result,
|
||||
fields: 0,
|
||||
empty_name: name.is_empty(),
|
||||
}
|
||||
DebugTuple { fmt, result, fields: 0, empty_name: name.is_empty() }
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
|
||||
|
@ -423,13 +408,7 @@ pub struct DebugSet<'a, 'b: 'a> {
|
|||
|
||||
pub(super) fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> {
|
||||
let result = fmt.write_str("{");
|
||||
DebugSet {
|
||||
inner: DebugInner {
|
||||
fmt,
|
||||
result,
|
||||
has_fields: false,
|
||||
},
|
||||
}
|
||||
DebugSet { inner: DebugInner { fmt, result, has_fields: false } }
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a> DebugSet<'a, 'b> {
|
||||
|
@ -487,8 +466,9 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
|
|||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn entries<D, I>(&mut self, entries: I) -> &mut DebugSet<'a, 'b>
|
||||
where D: fmt::Debug,
|
||||
I: IntoIterator<Item = D>
|
||||
where
|
||||
D: fmt::Debug,
|
||||
I: IntoIterator<Item = D>,
|
||||
{
|
||||
for entry in entries {
|
||||
self.entry(&entry);
|
||||
|
@ -560,13 +540,7 @@ pub struct DebugList<'a, 'b: 'a> {
|
|||
|
||||
pub(super) fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> {
|
||||
let result = fmt.write_str("[");
|
||||
DebugList {
|
||||
inner: DebugInner {
|
||||
fmt,
|
||||
result,
|
||||
has_fields: false,
|
||||
},
|
||||
}
|
||||
DebugList { inner: DebugInner { fmt, result, has_fields: false } }
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a> DebugList<'a, 'b> {
|
||||
|
@ -624,8 +598,9 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
|
|||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn entries<D, I>(&mut self, entries: I) -> &mut DebugList<'a, 'b>
|
||||
where D: fmt::Debug,
|
||||
I: IntoIterator<Item = D>
|
||||
where
|
||||
D: fmt::Debug,
|
||||
I: IntoIterator<Item = D>,
|
||||
{
|
||||
for entry in entries {
|
||||
self.entry(&entry);
|
||||
|
@ -702,13 +677,7 @@ pub struct DebugMap<'a, 'b: 'a> {
|
|||
|
||||
pub(super) fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
|
||||
let result = fmt.write_str("{");
|
||||
DebugMap {
|
||||
fmt,
|
||||
result,
|
||||
has_fields: false,
|
||||
has_key: false,
|
||||
state: Default::default(),
|
||||
}
|
||||
DebugMap { fmt, result, has_fields: false, has_key: false, state: Default::default() }
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a> DebugMap<'a, 'b> {
|
||||
|
@ -771,13 +740,14 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
|
|||
/// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
|
||||
/// );
|
||||
/// ```
|
||||
#[unstable(feature = "debug_map_key_value",
|
||||
reason = "recently added",
|
||||
issue = "62482")]
|
||||
#[unstable(feature = "debug_map_key_value", reason = "recently added", issue = "62482")]
|
||||
pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> {
|
||||
self.result = self.result.and_then(|_| {
|
||||
assert!(!self.has_key, "attempted to begin a new map entry \
|
||||
without completing the previous one");
|
||||
assert!(
|
||||
!self.has_key,
|
||||
"attempted to begin a new map entry \
|
||||
without completing the previous one"
|
||||
);
|
||||
|
||||
if self.is_pretty() {
|
||||
if !self.has_fields {
|
||||
|
@ -835,9 +805,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
|
|||
/// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
|
||||
/// );
|
||||
/// ```
|
||||
#[unstable(feature = "debug_map_key_value",
|
||||
reason = "recently added",
|
||||
issue = "62482")]
|
||||
#[unstable(feature = "debug_map_key_value", reason = "recently added", issue = "62482")]
|
||||
pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> {
|
||||
self.result = self.result.and_then(|_| {
|
||||
assert!(self.has_key, "attempted to format a map value before its key");
|
||||
|
@ -885,9 +853,10 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
|
|||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn entries<K, V, I>(&mut self, entries: I) -> &mut DebugMap<'a, 'b>
|
||||
where K: fmt::Debug,
|
||||
V: fmt::Debug,
|
||||
I: IntoIterator<Item = (K, V)>
|
||||
where
|
||||
K: fmt::Debug,
|
||||
V: fmt::Debug,
|
||||
I: IntoIterator<Item = (K, V)>,
|
||||
{
|
||||
for (k, v) in entries {
|
||||
self.entry(&k, &v);
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
|
||||
use crate::fmt;
|
||||
use crate::ops::{Div, Rem, Sub};
|
||||
use crate::str;
|
||||
use crate::slice;
|
||||
use crate::ptr;
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::ops::{Div, Rem, Sub};
|
||||
use crate::ptr;
|
||||
use crate::slice;
|
||||
use crate::str;
|
||||
|
||||
#[doc(hidden)]
|
||||
trait Int: PartialEq + PartialOrd + Div<Output=Self> + Rem<Output=Self> +
|
||||
Sub<Output=Self> + Copy {
|
||||
trait Int:
|
||||
PartialEq + PartialOrd + Div<Output = Self> + Rem<Output = Self> + Sub<Output = Self> + Copy
|
||||
{
|
||||
fn zero() -> Self;
|
||||
fn from_u8(u: u8) -> Self;
|
||||
fn to_u8(&self) -> u8;
|
||||
|
@ -60,33 +60,32 @@ trait GenericRadix {
|
|||
// Accumulate each digit of the number from the least significant
|
||||
// to the most significant figure.
|
||||
for byte in buf.iter_mut().rev() {
|
||||
let n = x % base; // Get the current place value.
|
||||
x = x / base; // Deaccumulate the number.
|
||||
let n = x % base; // Get the current place value.
|
||||
x = x / base; // Deaccumulate the number.
|
||||
byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer.
|
||||
curr -= 1;
|
||||
if x == zero {
|
||||
// No more digits left to accumulate.
|
||||
break
|
||||
break;
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// Do the same as above, but accounting for two's complement.
|
||||
for byte in buf.iter_mut().rev() {
|
||||
let n = zero - (x % base); // Get the current place value.
|
||||
x = x / base; // Deaccumulate the number.
|
||||
let n = zero - (x % base); // Get the current place value.
|
||||
x = x / base; // Deaccumulate the number.
|
||||
byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer.
|
||||
curr -= 1;
|
||||
if x == zero {
|
||||
// No more digits left to accumulate.
|
||||
break
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
let buf = &buf[curr..];
|
||||
let buf = unsafe { str::from_utf8_unchecked(slice::from_raw_parts(
|
||||
MaybeUninit::first_ptr(buf),
|
||||
buf.len()
|
||||
)) };
|
||||
let buf = unsafe {
|
||||
str::from_utf8_unchecked(slice::from_raw_parts(MaybeUninit::first_ptr(buf), buf.len()))
|
||||
};
|
||||
f.pad_integral(is_nonnegative, Self::PREFIX, buf)
|
||||
}
|
||||
}
|
||||
|
@ -125,9 +124,9 @@ macro_rules! radix {
|
|||
radix! { Binary, 2, "0b", x @ 0 ..= 1 => b'0' + x }
|
||||
radix! { Octal, 8, "0o", x @ 0 ..= 7 => b'0' + x }
|
||||
radix! { LowerHex, 16, "0x", x @ 0 ..= 9 => b'0' + x,
|
||||
x @ 10 ..= 15 => b'a' + (x - 10) }
|
||||
x @ 10 ..= 15 => b'a' + (x - 10) }
|
||||
radix! { UpperHex, 16, "0x", x @ 0 ..= 9 => b'0' + x,
|
||||
x @ 10 ..= 15 => b'A' + (x - 10) }
|
||||
x @ 10 ..= 15 => b'A' + (x - 10) }
|
||||
|
||||
macro_rules! int_base {
|
||||
($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
|
||||
|
@ -137,7 +136,7 @@ macro_rules! int_base {
|
|||
$Radix.fmt_int(*self as $U, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! debug {
|
||||
|
@ -155,7 +154,7 @@ macro_rules! debug {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! integer {
|
||||
|
@ -171,7 +170,7 @@ macro_rules! integer {
|
|||
int_base! { LowerHex for $Uint as $Uint -> LowerHex }
|
||||
int_base! { UpperHex for $Uint as $Uint -> UpperHex }
|
||||
debug! { $Uint }
|
||||
}
|
||||
};
|
||||
}
|
||||
integer! { isize, usize }
|
||||
integer! { i8, u8 }
|
||||
|
@ -180,9 +179,7 @@ integer! { i32, u32 }
|
|||
integer! { i64, u64 }
|
||||
integer! { i128, u128 }
|
||||
|
||||
|
||||
static DEC_DIGITS_LUT: &[u8; 200] =
|
||||
b"0001020304050607080910111213141516171819\
|
||||
static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\
|
||||
2021222324252627282930313233343536373839\
|
||||
4041424344454647484950515253545556575859\
|
||||
6061626364656667686970717273747576777879\
|
||||
|
|
|
@ -29,18 +29,22 @@
|
|||
//! guaranteed to happen in order. This is the standard mode for working
|
||||
//! with atomic types and is equivalent to Java's `volatile`.
|
||||
|
||||
#![unstable(feature = "core_intrinsics",
|
||||
reason = "intrinsics are unlikely to ever be stabilized, instead \
|
||||
#![unstable(
|
||||
feature = "core_intrinsics",
|
||||
reason = "intrinsics are unlikely to ever be stabilized, instead \
|
||||
they should be used through stabilized interfaces \
|
||||
in the rest of the standard library",
|
||||
issue = "none")]
|
||||
issue = "none"
|
||||
)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use crate::mem;
|
||||
|
||||
#[stable(feature = "drop_in_place", since = "1.8.0")]
|
||||
#[rustc_deprecated(reason = "no longer an intrinsic - use `ptr::drop_in_place` directly",
|
||||
since = "1.18.0")]
|
||||
#[rustc_deprecated(
|
||||
reason = "no longer an intrinsic - use `ptr::drop_in_place` directly",
|
||||
since = "1.18.0"
|
||||
)]
|
||||
pub use crate::ptr::drop_in_place;
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
|
@ -705,13 +709,14 @@ extern "rust-intrinsic" {
|
|||
/// which is unsafe unless `T` is `Copy`. Also, even if T is
|
||||
/// `Copy`, an all-zero value may not correspond to any legitimate
|
||||
/// state for the type in question.
|
||||
#[unstable(feature = "core_intrinsics",
|
||||
reason = "intrinsics are unlikely to ever be stabilized, instead \
|
||||
#[unstable(
|
||||
feature = "core_intrinsics",
|
||||
reason = "intrinsics are unlikely to ever be stabilized, instead \
|
||||
they should be used through stabilized interfaces \
|
||||
in the rest of the standard library",
|
||||
issue = "none")]
|
||||
#[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned",
|
||||
since = "1.38.0")]
|
||||
issue = "none"
|
||||
)]
|
||||
#[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", since = "1.38.0")]
|
||||
pub fn init<T>() -> T;
|
||||
|
||||
/// Creates an uninitialized value.
|
||||
|
@ -721,13 +726,14 @@ extern "rust-intrinsic" {
|
|||
/// state, which means it may claim either dropped or
|
||||
/// undropped. In the general case one must use `ptr::write` to
|
||||
/// initialize memory previous set to the result of `uninit`.
|
||||
#[unstable(feature = "core_intrinsics",
|
||||
reason = "intrinsics are unlikely to ever be stabilized, instead \
|
||||
#[unstable(
|
||||
feature = "core_intrinsics",
|
||||
reason = "intrinsics are unlikely to ever be stabilized, instead \
|
||||
they should be used through stabilized interfaces \
|
||||
in the rest of the standard library",
|
||||
issue = "none")]
|
||||
#[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned",
|
||||
since = "1.38.0")]
|
||||
issue = "none"
|
||||
)]
|
||||
#[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", since = "1.38.0")]
|
||||
pub fn uninit<T>() -> T;
|
||||
|
||||
/// Moves a value out of scope without running drop glue.
|
||||
|
@ -985,8 +991,7 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// The volatile parameter is set to `true`, so it will not be optimized out
|
||||
/// unless size is equal to zero.
|
||||
pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
|
||||
count: usize);
|
||||
pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize);
|
||||
/// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with
|
||||
/// a size of `count` * `size_of::<T>()` and an alignment of
|
||||
/// `min_align_of::<T>()`
|
||||
|
@ -1148,7 +1153,6 @@ extern "rust-intrinsic" {
|
|||
/// https://github.com/rust-lang/rust/issues/10184
|
||||
pub fn float_to_int_approx_unchecked<Float, Int>(value: Float) -> Int;
|
||||
|
||||
|
||||
/// Returns the number of bits set in an integer type `T`
|
||||
pub fn ctpop<T>(x: T) -> T;
|
||||
|
||||
|
@ -1376,11 +1380,7 @@ fn overlaps<T>(src: *const T, dst: *const T, count: usize) -> bool {
|
|||
let src_usize = src as usize;
|
||||
let dst_usize = dst as usize;
|
||||
let size = mem::size_of::<T>().checked_mul(count).unwrap();
|
||||
let diff = if src_usize > dst_usize {
|
||||
src_usize - dst_usize
|
||||
} else {
|
||||
dst_usize - src_usize
|
||||
};
|
||||
let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize };
|
||||
size > diff
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::ops::Try;
|
||||
use crate::usize;
|
||||
|
||||
use super::super::{Iterator, DoubleEndedIterator, FusedIterator, TrustedLen};
|
||||
use super::super::{DoubleEndedIterator, FusedIterator, Iterator, TrustedLen};
|
||||
|
||||
/// An iterator that links two iterators together, in a chain.
|
||||
///
|
||||
|
@ -48,9 +48,10 @@ enum ChainState {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A, B> Iterator for Chain<A, B> where
|
||||
impl<A, B> Iterator for Chain<A, B>
|
||||
where
|
||||
A: Iterator,
|
||||
B: Iterator<Item = A::Item>
|
||||
B: Iterator<Item = A::Item>,
|
||||
{
|
||||
type Item = A::Item;
|
||||
|
||||
|
@ -79,8 +80,11 @@ impl<A, B> Iterator for Chain<A, B> where
|
|||
}
|
||||
}
|
||||
|
||||
fn try_fold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R where
|
||||
Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
|
||||
fn try_fold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
let mut accum = init;
|
||||
match self.state {
|
||||
|
@ -90,7 +94,7 @@ impl<A, B> Iterator for Chain<A, B> where
|
|||
self.state = ChainState::Back;
|
||||
}
|
||||
}
|
||||
_ => { }
|
||||
_ => {}
|
||||
}
|
||||
if let ChainState::Back = self.state {
|
||||
accum = self.b.try_fold(accum, &mut f)?;
|
||||
|
@ -99,20 +103,21 @@ impl<A, B> Iterator for Chain<A, B> where
|
|||
}
|
||||
|
||||
fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
|
||||
where F: FnMut(Acc, Self::Item) -> Acc,
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
let mut accum = init;
|
||||
match self.state {
|
||||
ChainState::Both | ChainState::Front => {
|
||||
accum = self.a.fold(accum, &mut f);
|
||||
}
|
||||
_ => { }
|
||||
_ => {}
|
||||
}
|
||||
match self.state {
|
||||
ChainState::Both | ChainState::Back => {
|
||||
accum = self.b.fold(accum, &mut f);
|
||||
}
|
||||
_ => { }
|
||||
_ => {}
|
||||
}
|
||||
accum
|
||||
}
|
||||
|
@ -123,7 +128,7 @@ impl<A, B> Iterator for Chain<A, B> where
|
|||
ChainState::Both | ChainState::Front => {
|
||||
for x in self.a.by_ref() {
|
||||
if n == 0 {
|
||||
return Some(x)
|
||||
return Some(x);
|
||||
}
|
||||
n -= 1;
|
||||
}
|
||||
|
@ -133,15 +138,12 @@ impl<A, B> Iterator for Chain<A, B> where
|
|||
}
|
||||
ChainState::Back => {}
|
||||
}
|
||||
if let ChainState::Back = self.state {
|
||||
self.b.nth(n)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if let ChainState::Back = self.state { self.b.nth(n) } else { None }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
|
||||
fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
match self.state {
|
||||
|
@ -150,7 +152,7 @@ impl<A, B> Iterator for Chain<A, B> where
|
|||
self.state = ChainState::Back;
|
||||
self.b.find(predicate)
|
||||
}
|
||||
v => v
|
||||
v => v,
|
||||
},
|
||||
ChainState::Front => self.a.find(predicate),
|
||||
ChainState::Back => self.b.find(predicate),
|
||||
|
@ -165,9 +167,9 @@ impl<A, B> Iterator for Chain<A, B> where
|
|||
let a_last = self.a.last();
|
||||
let b_last = self.b.last();
|
||||
b_last.or(a_last)
|
||||
},
|
||||
}
|
||||
ChainState::Front => self.a.last(),
|
||||
ChainState::Back => self.b.last()
|
||||
ChainState::Back => self.b.last(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,7 +184,7 @@ impl<A, B> Iterator for Chain<A, B> where
|
|||
|
||||
let upper = match (a_upper, b_upper) {
|
||||
(Some(x), Some(y)) => x.checked_add(y),
|
||||
_ => None
|
||||
_ => None,
|
||||
};
|
||||
|
||||
(lower, upper)
|
||||
|
@ -194,9 +196,10 @@ impl<A, B> Iterator for Chain<A, B> where
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A, B> DoubleEndedIterator for Chain<A, B> where
|
||||
impl<A, B> DoubleEndedIterator for Chain<A, B>
|
||||
where
|
||||
A: DoubleEndedIterator,
|
||||
B: DoubleEndedIterator<Item=A::Item>,
|
||||
B: DoubleEndedIterator<Item = A::Item>,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<A::Item> {
|
||||
|
@ -219,7 +222,7 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where
|
|||
ChainState::Both | ChainState::Back => {
|
||||
for x in self.b.by_ref().rev() {
|
||||
if n == 0 {
|
||||
return Some(x)
|
||||
return Some(x);
|
||||
}
|
||||
n -= 1;
|
||||
}
|
||||
|
@ -229,15 +232,14 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where
|
|||
}
|
||||
ChainState::Front => {}
|
||||
}
|
||||
if let ChainState::Front = self.state {
|
||||
self.a.nth_back(n)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if let ChainState::Front = self.state { self.a.nth_back(n) } else { None }
|
||||
}
|
||||
|
||||
fn try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R where
|
||||
Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
|
||||
fn try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
let mut accum = init;
|
||||
match self.state {
|
||||
|
@ -247,7 +249,7 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where
|
|||
self.state = ChainState::Front;
|
||||
}
|
||||
}
|
||||
_ => { }
|
||||
_ => {}
|
||||
}
|
||||
if let ChainState::Front = self.state {
|
||||
accum = self.a.try_rfold(accum, &mut f)?;
|
||||
|
@ -256,34 +258,39 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where
|
|||
}
|
||||
|
||||
fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc
|
||||
where F: FnMut(Acc, Self::Item) -> Acc,
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
let mut accum = init;
|
||||
match self.state {
|
||||
ChainState::Both | ChainState::Back => {
|
||||
accum = self.b.rfold(accum, &mut f);
|
||||
}
|
||||
_ => { }
|
||||
_ => {}
|
||||
}
|
||||
match self.state {
|
||||
ChainState::Both | ChainState::Front => {
|
||||
accum = self.a.rfold(accum, &mut f);
|
||||
}
|
||||
_ => { }
|
||||
_ => {}
|
||||
}
|
||||
accum
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Note: *both* must be fused to handle double-ended iterators.
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<A, B> FusedIterator for Chain<A, B>
|
||||
where A: FusedIterator,
|
||||
B: FusedIterator<Item=A::Item>,
|
||||
{}
|
||||
where
|
||||
A: FusedIterator,
|
||||
B: FusedIterator<Item = A::Item>,
|
||||
{
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<A, B> TrustedLen for Chain<A, B>
|
||||
where A: TrustedLen, B: TrustedLen<Item=A::Item>,
|
||||
{}
|
||||
where
|
||||
A: TrustedLen,
|
||||
B: TrustedLen<Item = A::Item>,
|
||||
{
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use crate::cmp;
|
||||
|
||||
use super::super::{Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen};
|
||||
use super::super::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedLen};
|
||||
|
||||
/// An iterator that iterates two other iterators simultaneously.
|
||||
///
|
||||
|
@ -27,7 +27,9 @@ impl<A: Iterator, B: Iterator> Zip<A, B> {
|
|||
}
|
||||
fn super_nth(&mut self, mut n: usize) -> Option<(A::Item, B::Item)> {
|
||||
while let Some(x) = Iterator::next(self) {
|
||||
if n == 0 { return Some(x) }
|
||||
if n == 0 {
|
||||
return Some(x);
|
||||
}
|
||||
n -= 1;
|
||||
}
|
||||
None
|
||||
|
@ -35,7 +37,10 @@ impl<A: Iterator, B: Iterator> Zip<A, B> {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A, B> Iterator for Zip<A, B> where A: Iterator, B: Iterator
|
||||
impl<A, B> Iterator for Zip<A, B>
|
||||
where
|
||||
A: Iterator,
|
||||
B: Iterator,
|
||||
{
|
||||
type Item = (A::Item, B::Item);
|
||||
|
||||
|
@ -56,7 +61,8 @@ impl<A, B> Iterator for Zip<A, B> where A: Iterator, B: Iterator
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A, B> DoubleEndedIterator for Zip<A, B> where
|
||||
impl<A, B> DoubleEndedIterator for Zip<A, B>
|
||||
where
|
||||
A: DoubleEndedIterator + ExactSizeIterator,
|
||||
B: DoubleEndedIterator + ExactSizeIterator,
|
||||
{
|
||||
|
@ -75,14 +81,17 @@ trait ZipImpl<A, B> {
|
|||
fn size_hint(&self) -> (usize, Option<usize>);
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item>;
|
||||
fn next_back(&mut self) -> Option<Self::Item>
|
||||
where A: DoubleEndedIterator + ExactSizeIterator,
|
||||
B: DoubleEndedIterator + ExactSizeIterator;
|
||||
where
|
||||
A: DoubleEndedIterator + ExactSizeIterator,
|
||||
B: DoubleEndedIterator + ExactSizeIterator;
|
||||
}
|
||||
|
||||
// General Zip impl
|
||||
#[doc(hidden)]
|
||||
impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
||||
where A: Iterator, B: Iterator
|
||||
where
|
||||
A: Iterator,
|
||||
B: Iterator,
|
||||
{
|
||||
type Item = (A::Item, B::Item);
|
||||
default fn new(a: A, b: B) -> Self {
|
||||
|
@ -90,7 +99,7 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
|||
a,
|
||||
b,
|
||||
index: 0, // unused
|
||||
len: 0, // unused
|
||||
len: 0, // unused
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,17 +117,22 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
|||
|
||||
#[inline]
|
||||
default fn next_back(&mut self) -> Option<(A::Item, B::Item)>
|
||||
where A: DoubleEndedIterator + ExactSizeIterator,
|
||||
B: DoubleEndedIterator + ExactSizeIterator
|
||||
where
|
||||
A: DoubleEndedIterator + ExactSizeIterator,
|
||||
B: DoubleEndedIterator + ExactSizeIterator,
|
||||
{
|
||||
let a_sz = self.a.len();
|
||||
let b_sz = self.b.len();
|
||||
if a_sz != b_sz {
|
||||
// Adjust a, b to equal length
|
||||
if a_sz > b_sz {
|
||||
for _ in 0..a_sz - b_sz { self.a.next_back(); }
|
||||
for _ in 0..a_sz - b_sz {
|
||||
self.a.next_back();
|
||||
}
|
||||
} else {
|
||||
for _ in 0..b_sz - a_sz { self.b.next_back(); }
|
||||
for _ in 0..b_sz - a_sz {
|
||||
self.b.next_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
match (self.a.next_back(), self.b.next_back()) {
|
||||
|
@ -136,10 +150,10 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
|||
let lower = cmp::min(a_lower, b_lower);
|
||||
|
||||
let upper = match (a_upper, b_upper) {
|
||||
(Some(x), Some(y)) => Some(cmp::min(x,y)),
|
||||
(Some(x), Some(y)) => Some(cmp::min(x, y)),
|
||||
(Some(x), None) => Some(x),
|
||||
(None, Some(y)) => Some(y),
|
||||
(None, None) => None
|
||||
(None, None) => None,
|
||||
};
|
||||
|
||||
(lower, upper)
|
||||
|
@ -148,16 +162,13 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
|||
|
||||
#[doc(hidden)]
|
||||
impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
||||
where A: TrustedRandomAccess, B: TrustedRandomAccess
|
||||
where
|
||||
A: TrustedRandomAccess,
|
||||
B: TrustedRandomAccess,
|
||||
{
|
||||
fn new(a: A, b: B) -> Self {
|
||||
let len = cmp::min(a.len(), b.len());
|
||||
Zip {
|
||||
a,
|
||||
b,
|
||||
index: 0,
|
||||
len,
|
||||
}
|
||||
Zip { a, b, index: 0, len }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -165,9 +176,7 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
|||
if self.index < self.len {
|
||||
let i = self.index;
|
||||
self.index += 1;
|
||||
unsafe {
|
||||
Some((self.a.get_unchecked(i), self.b.get_unchecked(i)))
|
||||
}
|
||||
unsafe { Some((self.a.get_unchecked(i), self.b.get_unchecked(i))) }
|
||||
} else if A::may_have_side_effect() && self.index < self.a.len() {
|
||||
// match the base implementation's potential side effects
|
||||
unsafe {
|
||||
|
@ -194,10 +203,14 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
|||
let i = self.index;
|
||||
self.index += 1;
|
||||
if A::may_have_side_effect() {
|
||||
unsafe { self.a.get_unchecked(i); }
|
||||
unsafe {
|
||||
self.a.get_unchecked(i);
|
||||
}
|
||||
}
|
||||
if B::may_have_side_effect() {
|
||||
unsafe { self.b.get_unchecked(i); }
|
||||
unsafe {
|
||||
self.b.get_unchecked(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,8 +219,9 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
|||
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<(A::Item, B::Item)>
|
||||
where A: DoubleEndedIterator + ExactSizeIterator,
|
||||
B: DoubleEndedIterator + ExactSizeIterator
|
||||
where
|
||||
A: DoubleEndedIterator + ExactSizeIterator,
|
||||
B: DoubleEndedIterator + ExactSizeIterator,
|
||||
{
|
||||
// Adjust a, b to equal length
|
||||
if A::may_have_side_effect() {
|
||||
|
@ -229,9 +243,7 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
|||
if self.index < self.len {
|
||||
self.len -= 1;
|
||||
let i = self.len;
|
||||
unsafe {
|
||||
Some((self.a.get_unchecked(i), self.b.get_unchecked(i)))
|
||||
}
|
||||
unsafe { Some((self.a.get_unchecked(i), self.b.get_unchecked(i))) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -240,12 +252,17 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
|||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A, B> ExactSizeIterator for Zip<A, B>
|
||||
where A: ExactSizeIterator, B: ExactSizeIterator {}
|
||||
where
|
||||
A: ExactSizeIterator,
|
||||
B: ExactSizeIterator,
|
||||
{
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe impl<A, B> TrustedRandomAccess for Zip<A, B>
|
||||
where A: TrustedRandomAccess,
|
||||
B: TrustedRandomAccess,
|
||||
where
|
||||
A: TrustedRandomAccess,
|
||||
B: TrustedRandomAccess,
|
||||
{
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> (A::Item, B::Item) {
|
||||
(self.a.get_unchecked(i), self.b.get_unchecked(i))
|
||||
|
@ -258,12 +275,19 @@ unsafe impl<A, B> TrustedRandomAccess for Zip<A, B>
|
|||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<A, B> FusedIterator for Zip<A, B>
|
||||
where A: FusedIterator, B: FusedIterator, {}
|
||||
where
|
||||
A: FusedIterator,
|
||||
B: FusedIterator,
|
||||
{
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<A, B> TrustedLen for Zip<A, B>
|
||||
where A: TrustedLen, B: TrustedLen,
|
||||
{}
|
||||
where
|
||||
A: TrustedLen,
|
||||
B: TrustedLen,
|
||||
{
|
||||
}
|
||||
|
||||
/// An iterator whose items are random-accessible efficiently
|
||||
///
|
||||
|
@ -275,7 +299,7 @@ unsafe impl<A, B> TrustedLen for Zip<A, B>
|
|||
/// .get_unchecked() must return distinct mutable references for distinct
|
||||
/// indices (if applicable), and must return a valid reference if index is in
|
||||
/// 0..self.len().
|
||||
pub(crate) unsafe trait TrustedRandomAccess : ExactSizeIterator {
|
||||
pub(crate) unsafe trait TrustedRandomAccess: ExactSizeIterator {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item;
|
||||
/// Returns `true` if getting an iterator element may have
|
||||
/// side effects. Remember to take inner iterators into account.
|
||||
|
|
|
@ -309,56 +309,58 @@ use crate::ops::Try;
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::traits::Iterator;
|
||||
|
||||
#[unstable(feature = "step_trait",
|
||||
reason = "likely to be replaced by finer-grained traits",
|
||||
issue = "42168")]
|
||||
#[unstable(
|
||||
feature = "step_trait",
|
||||
reason = "likely to be replaced by finer-grained traits",
|
||||
issue = "42168"
|
||||
)]
|
||||
pub use self::range::Step;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::sources::{Repeat, repeat};
|
||||
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
|
||||
pub use self::sources::{RepeatWith, repeat_with};
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
pub use self::sources::{Empty, empty};
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
pub use self::sources::{Once, once};
|
||||
#[unstable(feature = "iter_once_with", issue = "57581")]
|
||||
pub use self::sources::{OnceWith, once_with};
|
||||
pub use self::sources::{empty, Empty};
|
||||
#[stable(feature = "iter_from_fn", since = "1.34.0")]
|
||||
pub use self::sources::{FromFn, from_fn};
|
||||
pub use self::sources::{from_fn, FromFn};
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
pub use self::sources::{once, Once};
|
||||
#[unstable(feature = "iter_once_with", issue = "57581")]
|
||||
pub use self::sources::{once_with, OnceWith};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::sources::{repeat, Repeat};
|
||||
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
|
||||
pub use self::sources::{repeat_with, RepeatWith};
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
pub use self::sources::{Successors, successors};
|
||||
pub use self::sources::{successors, Successors};
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::traits::{ExactSizeIterator, Sum, Product};
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
pub use self::traits::FusedIterator;
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
pub use self::traits::TrustedLen;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::traits::{DoubleEndedIterator, Extend, FromIterator, IntoIterator};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::traits::{ExactSizeIterator, Product, Sum};
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::adapters::{Rev, Cycle, Chain, Zip, Map, Filter, FilterMap, Enumerate};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::adapters::{Peekable, SkipWhile, TakeWhile, Skip, Take, Scan, FlatMap};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::adapters::{Fuse, Inspect};
|
||||
#[stable(feature = "iter_cloned", since = "1.1.0")]
|
||||
pub use self::adapters::Cloned;
|
||||
#[stable(feature = "iterator_step_by", since = "1.28.0")]
|
||||
pub use self::adapters::StepBy;
|
||||
#[stable(feature = "iterator_flatten", since = "1.29.0")]
|
||||
pub use self::adapters::Flatten;
|
||||
#[stable(feature = "iter_copied", since = "1.36.0")]
|
||||
pub use self::adapters::Copied;
|
||||
#[stable(feature = "iterator_flatten", since = "1.29.0")]
|
||||
pub use self::adapters::Flatten;
|
||||
#[stable(feature = "iterator_step_by", since = "1.28.0")]
|
||||
pub use self::adapters::StepBy;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::adapters::{Chain, Cycle, Enumerate, Filter, FilterMap, Map, Rev, Zip};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::adapters::{FlatMap, Peekable, Scan, Skip, SkipWhile, Take, TakeWhile};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::adapters::{Fuse, Inspect};
|
||||
|
||||
pub(crate) use self::adapters::{TrustedRandomAccess, process_results};
|
||||
pub(crate) use self::adapters::{process_results, TrustedRandomAccess};
|
||||
|
||||
mod adapters;
|
||||
mod range;
|
||||
mod sources;
|
||||
mod traits;
|
||||
mod adapters;
|
||||
|
||||
/// Used to make try_fold closures more like normal loops
|
||||
#[derive(PartialEq)]
|
||||
|
@ -378,9 +380,13 @@ impl<C, B> Try for LoopState<C, B> {
|
|||
}
|
||||
}
|
||||
#[inline]
|
||||
fn from_error(v: Self::Error) -> Self { LoopState::Break(v) }
|
||||
fn from_error(v: Self::Error) -> Self {
|
||||
LoopState::Break(v)
|
||||
}
|
||||
#[inline]
|
||||
fn from_ok(v: Self::Ok) -> Self { LoopState::Continue(v) }
|
||||
fn from_ok(v: Self::Ok) -> Self {
|
||||
LoopState::Continue(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, B> LoopState<C, B> {
|
||||
|
|
|
@ -9,9 +9,11 @@ use super::{FusedIterator, TrustedLen};
|
|||
///
|
||||
/// The `steps_between` function provides a way to efficiently compare
|
||||
/// two `Step` objects.
|
||||
#[unstable(feature = "step_trait",
|
||||
reason = "likely to be replaced by finer-grained traits",
|
||||
issue = "42168")]
|
||||
#[unstable(
|
||||
feature = "step_trait",
|
||||
reason = "likely to be replaced by finer-grained traits",
|
||||
issue = "42168"
|
||||
)]
|
||||
pub trait Step: Clone + PartialOrd + Sized {
|
||||
/// Returns the number of steps between two step objects. The count is
|
||||
/// inclusive of `start` and exclusive of `end`.
|
||||
|
@ -170,8 +172,8 @@ macro_rules! step_impl_signed {
|
|||
}
|
||||
|
||||
step_impl_unsigned!(usize u8 u16 u32 u64 u128);
|
||||
step_impl_signed!([isize: usize] [i8: u8] [i16: u16]);
|
||||
step_impl_signed!([i32: u32] [i64: u64] [i128: u128]);
|
||||
step_impl_signed!([isize: usize][i8: u8][i16: u16]);
|
||||
step_impl_signed!([i32: u32][i64: u64][i128: u128]);
|
||||
|
||||
macro_rules! range_exact_iter_impl {
|
||||
($($t:ty)*) => ($(
|
||||
|
@ -227,7 +229,7 @@ impl<A: Step> Iterator for ops::Range<A> {
|
|||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
match Step::steps_between(&self.start, &self.end) {
|
||||
Some(hint) => (hint, Some(hint)),
|
||||
None => (usize::MAX, None)
|
||||
None => (usize::MAX, None),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,7 +238,7 @@ impl<A: Step> Iterator for ops::Range<A> {
|
|||
if let Some(plus_n) = self.start.add_usize(n) {
|
||||
if plus_n < self.end {
|
||||
self.start = plus_n.add_one();
|
||||
return Some(plus_n)
|
||||
return Some(plus_n);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,7 +293,7 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> {
|
|||
if let Some(minus_n) = self.end.sub_usize(n) {
|
||||
if minus_n > self.start {
|
||||
self.end = minus_n.sub_one();
|
||||
return Some(self.end.clone())
|
||||
return Some(self.end.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,7 +398,9 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
|
|||
#[inline]
|
||||
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||
where
|
||||
Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
{
|
||||
self.compute_is_empty();
|
||||
|
||||
|
@ -484,8 +488,11 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where
|
||||
Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
|
||||
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
{
|
||||
self.compute_is_empty();
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ impl<I: FusedIterator + ?Sized> FusedIterator for &mut I {}
|
|||
/// [`usize::MAX`]: ../../std/usize/constant.MAX.html
|
||||
/// [`.size_hint`]: ../../std/iter/trait.Iterator.html#method.size_hint
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
pub unsafe trait TrustedLen : Iterator {}
|
||||
pub unsafe trait TrustedLen: Iterator {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<I: TrustedLen + ?Sized> TrustedLen for &mut I {}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
mod iterator;
|
||||
mod accum;
|
||||
mod collect;
|
||||
mod double_ended;
|
||||
mod exact_size;
|
||||
mod collect;
|
||||
mod accum;
|
||||
mod iterator;
|
||||
mod marker;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::iterator::Iterator;
|
||||
pub use self::accum::{Product, Sum};
|
||||
pub use self::collect::{Extend, FromIterator, IntoIterator};
|
||||
pub use self::double_ended::DoubleEndedIterator;
|
||||
pub use self::exact_size::ExactSizeIterator;
|
||||
pub use self::collect::{FromIterator, IntoIterator, Extend};
|
||||
pub use self::accum::{Sum, Product};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::iterator::Iterator;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::marker::{FusedIterator, TrustedLen};
|
||||
|
|
|
@ -49,22 +49,21 @@
|
|||
//
|
||||
// This cfg won't affect doc tests.
|
||||
#![cfg(not(test))]
|
||||
|
||||
#![stable(feature = "core", since = "1.6.0")]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
|
||||
html_playground_url = "https://play.rust-lang.org/",
|
||||
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
|
||||
test(no_crate_inject, attr(deny(warnings))),
|
||||
test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
|
||||
#![doc(
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/",
|
||||
html_playground_url = "https://play.rust-lang.org/",
|
||||
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
|
||||
test(no_crate_inject, attr(deny(warnings))),
|
||||
test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
|
||||
)]
|
||||
#![no_core]
|
||||
|
||||
#![warn(deprecated_in_future)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(missing_debug_implementations)]
|
||||
#![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings
|
||||
#![allow(explicit_outlives_requirements)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
#![feature(allow_internal_unstable)]
|
||||
#![feature(arbitrary_self_types)]
|
||||
#![feature(asm)]
|
||||
|
@ -148,22 +147,36 @@ mod int_macros;
|
|||
#[macro_use]
|
||||
mod uint_macros;
|
||||
|
||||
#[path = "num/isize.rs"] pub mod isize;
|
||||
#[path = "num/i8.rs"] pub mod i8;
|
||||
#[path = "num/i16.rs"] pub mod i16;
|
||||
#[path = "num/i32.rs"] pub mod i32;
|
||||
#[path = "num/i64.rs"] pub mod i64;
|
||||
#[path = "num/i128.rs"] pub mod i128;
|
||||
#[path = "num/i128.rs"]
|
||||
pub mod i128;
|
||||
#[path = "num/i16.rs"]
|
||||
pub mod i16;
|
||||
#[path = "num/i32.rs"]
|
||||
pub mod i32;
|
||||
#[path = "num/i64.rs"]
|
||||
pub mod i64;
|
||||
#[path = "num/i8.rs"]
|
||||
pub mod i8;
|
||||
#[path = "num/isize.rs"]
|
||||
pub mod isize;
|
||||
|
||||
#[path = "num/usize.rs"] pub mod usize;
|
||||
#[path = "num/u8.rs"] pub mod u8;
|
||||
#[path = "num/u16.rs"] pub mod u16;
|
||||
#[path = "num/u32.rs"] pub mod u32;
|
||||
#[path = "num/u64.rs"] pub mod u64;
|
||||
#[path = "num/u128.rs"] pub mod u128;
|
||||
#[path = "num/u128.rs"]
|
||||
pub mod u128;
|
||||
#[path = "num/u16.rs"]
|
||||
pub mod u16;
|
||||
#[path = "num/u32.rs"]
|
||||
pub mod u32;
|
||||
#[path = "num/u64.rs"]
|
||||
pub mod u64;
|
||||
#[path = "num/u8.rs"]
|
||||
pub mod u8;
|
||||
#[path = "num/usize.rs"]
|
||||
pub mod usize;
|
||||
|
||||
#[path = "num/f32.rs"] pub mod f32;
|
||||
#[path = "num/f64.rs"] pub mod f64;
|
||||
#[path = "num/f32.rs"]
|
||||
pub mod f32;
|
||||
#[path = "num/f64.rs"]
|
||||
pub mod f64;
|
||||
|
||||
#[macro_use]
|
||||
pub mod num;
|
||||
|
@ -174,24 +187,24 @@ pub mod prelude;
|
|||
|
||||
/* Core modules for ownership management */
|
||||
|
||||
pub mod hint;
|
||||
pub mod intrinsics;
|
||||
pub mod mem;
|
||||
pub mod ptr;
|
||||
pub mod hint;
|
||||
|
||||
/* Core language traits */
|
||||
|
||||
#[cfg(not(test))] // See #65860
|
||||
pub mod marker;
|
||||
pub mod ops;
|
||||
#[cfg(not(test))] // See #65860
|
||||
pub mod cmp;
|
||||
pub mod borrow;
|
||||
#[cfg(not(test))] // See #65860
|
||||
pub mod clone;
|
||||
#[cfg(not(test))] // See #65860
|
||||
pub mod default;
|
||||
pub mod cmp;
|
||||
pub mod convert;
|
||||
pub mod borrow;
|
||||
#[cfg(not(test))] // See #65860
|
||||
pub mod default;
|
||||
#[cfg(not(test))] // See #65860
|
||||
pub mod marker;
|
||||
pub mod ops;
|
||||
|
||||
/* Core types and methods on primitives */
|
||||
|
||||
|
@ -199,27 +212,27 @@ pub mod any;
|
|||
#[cfg(not(test))] // See #65860
|
||||
pub mod array;
|
||||
pub mod ascii;
|
||||
pub mod sync;
|
||||
pub mod cell;
|
||||
pub mod char;
|
||||
pub mod ffi;
|
||||
#[cfg(not(test))] // See #65860
|
||||
pub mod iter;
|
||||
pub mod option;
|
||||
pub mod panic;
|
||||
pub mod panicking;
|
||||
#[cfg(not(test))] // See #65860
|
||||
pub mod pin;
|
||||
#[cfg(not(test))] // See #65860
|
||||
pub mod iter;
|
||||
pub mod option;
|
||||
pub mod raw;
|
||||
pub mod result;
|
||||
pub mod ffi;
|
||||
pub mod sync;
|
||||
|
||||
#[cfg(not(test))] // See #65860
|
||||
pub mod fmt;
|
||||
#[cfg(not(test))] // See #65860
|
||||
pub mod hash;
|
||||
pub mod slice;
|
||||
#[cfg(not(test))] // See #65860
|
||||
pub mod str;
|
||||
#[cfg(not(test))] // See #65860
|
||||
pub mod hash;
|
||||
#[cfg(not(test))] // See #65860
|
||||
pub mod fmt;
|
||||
pub mod time;
|
||||
|
||||
pub mod unicode;
|
||||
|
|
|
@ -31,17 +31,17 @@ use crate::hash::Hasher;
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "send_trait")]
|
||||
#[rustc_on_unimplemented(
|
||||
message="`{Self}` cannot be sent between threads safely",
|
||||
label="`{Self}` cannot be sent between threads safely"
|
||||
message = "`{Self}` cannot be sent between threads safely",
|
||||
label = "`{Self}` cannot be sent between threads safely"
|
||||
)]
|
||||
pub unsafe auto trait Send {
|
||||
// empty.
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> !Send for *const T { }
|
||||
impl<T: ?Sized> !Send for *const T {}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> !Send for *mut T { }
|
||||
impl<T: ?Sized> !Send for *mut T {}
|
||||
|
||||
/// Types with a constant size known at compile time.
|
||||
///
|
||||
|
@ -83,11 +83,11 @@ impl<T: ?Sized> !Send for *mut T { }
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[lang = "sized"]
|
||||
#[rustc_on_unimplemented(
|
||||
on(parent_trait="std::path::Path", label="borrow the `Path` instead"),
|
||||
message="the size for values of type `{Self}` cannot be known at compilation time",
|
||||
label="doesn't have a size known at compile-time",
|
||||
note="to learn more, visit <https://doc.rust-lang.org/book/\
|
||||
ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>",
|
||||
on(parent_trait = "std::path::Path", label = "borrow the `Path` instead"),
|
||||
message = "the size for values of type `{Self}` cannot be known at compilation time",
|
||||
label = "doesn't have a size known at compile-time",
|
||||
note = "to learn more, visit <https://doc.rust-lang.org/book/\
|
||||
ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>"
|
||||
)]
|
||||
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
|
||||
pub trait Sized {
|
||||
|
@ -148,7 +148,7 @@ pub trait Unsize<T: ?Sized> {
|
|||
/// [RFC1445]: https://github.com/rust-lang/rfcs/blob/master/text/1445-restrict-constants-in-patterns.md
|
||||
/// [issue 63438]: https://github.com/rust-lang/rust/issues/63438
|
||||
#[unstable(feature = "structural_match", issue = "31434")]
|
||||
#[rustc_on_unimplemented(message="the type `{Self}` does not `#[derive(PartialEq)]`")]
|
||||
#[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")]
|
||||
#[lang = "structural_peq"]
|
||||
pub trait StructuralPartialEq {
|
||||
// Empty.
|
||||
|
@ -198,7 +198,7 @@ pub trait StructuralPartialEq {
|
|||
/// of the two derives (`#[derive(PartialEq)]` and `#[derive(Eq)]`) and check
|
||||
/// that both of them are present as part of structural-match checking.
|
||||
#[unstable(feature = "structural_match", issue = "31434")]
|
||||
#[rustc_on_unimplemented(message="the type `{Self}` does not `#[derive(Eq)]`")]
|
||||
#[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")]
|
||||
#[lang = "structural_teq"]
|
||||
pub trait StructuralEq {
|
||||
// Empty.
|
||||
|
@ -362,7 +362,7 @@ pub trait StructuralEq {
|
|||
/// [impls]: #implementors
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[lang = "copy"]
|
||||
pub trait Copy : Clone {
|
||||
pub trait Copy: Clone {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
|
@ -370,7 +370,9 @@ pub trait Copy : Clone {
|
|||
#[rustc_builtin_macro]
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
#[allow_internal_unstable(core_intrinsics, derive_clone_copy)]
|
||||
pub macro Copy($item:item) { /* compiler built-in */ }
|
||||
pub macro Copy($item:item) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
/// Types for which it is safe to share references between threads.
|
||||
///
|
||||
|
@ -444,8 +446,8 @@ pub macro Copy($item:item) { /* compiler built-in */ }
|
|||
#[cfg_attr(not(test), rustc_diagnostic_item = "sync_trait")]
|
||||
#[lang = "sync"]
|
||||
#[rustc_on_unimplemented(
|
||||
message="`{Self}` cannot be shared between threads safely",
|
||||
label="`{Self}` cannot be shared between threads safely"
|
||||
message = "`{Self}` cannot be shared between threads safely",
|
||||
label = "`{Self}` cannot be shared between threads safely"
|
||||
)]
|
||||
pub unsafe auto trait Sync {
|
||||
// FIXME(estebank): once support to add notes in `rustc_on_unimplemented`
|
||||
|
@ -462,67 +464,65 @@ pub unsafe auto trait Sync {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> !Sync for *const T { }
|
||||
impl<T: ?Sized> !Sync for *const T {}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> !Sync for *mut T { }
|
||||
impl<T: ?Sized> !Sync for *mut T {}
|
||||
|
||||
macro_rules! impls{
|
||||
($t: ident) => (
|
||||
macro_rules! impls {
|
||||
($t: ident) => {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T:?Sized> Hash for $t<T> {
|
||||
impl<T: ?Sized> Hash for $t<T> {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, _: &mut H) {
|
||||
}
|
||||
fn hash<H: Hasher>(&self, _: &mut H) {}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T:?Sized> cmp::PartialEq for $t<T> {
|
||||
impl<T: ?Sized> cmp::PartialEq for $t<T> {
|
||||
fn eq(&self, _other: &$t<T>) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T:?Sized> cmp::Eq for $t<T> {
|
||||
}
|
||||
impl<T: ?Sized> cmp::Eq for $t<T> {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T:?Sized> cmp::PartialOrd for $t<T> {
|
||||
impl<T: ?Sized> cmp::PartialOrd for $t<T> {
|
||||
fn partial_cmp(&self, _other: &$t<T>) -> Option<cmp::Ordering> {
|
||||
Option::Some(cmp::Ordering::Equal)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T:?Sized> cmp::Ord for $t<T> {
|
||||
impl<T: ?Sized> cmp::Ord for $t<T> {
|
||||
fn cmp(&self, _other: &$t<T>) -> cmp::Ordering {
|
||||
cmp::Ordering::Equal
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T:?Sized> Copy for $t<T> { }
|
||||
impl<T: ?Sized> Copy for $t<T> {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T:?Sized> Clone for $t<T> {
|
||||
impl<T: ?Sized> Clone for $t<T> {
|
||||
fn clone(&self) -> $t<T> {
|
||||
$t
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T:?Sized> Default for $t<T> {
|
||||
impl<T: ?Sized> Default for $t<T> {
|
||||
fn default() -> $t<T> {
|
||||
$t
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "structural_match", issue = "31434")]
|
||||
impl<T: ?Sized> StructuralPartialEq for $t<T> { }
|
||||
impl<T: ?Sized> StructuralPartialEq for $t<T> {}
|
||||
|
||||
#[unstable(feature = "structural_match", issue = "31434")]
|
||||
impl<T: ?Sized> StructuralEq for $t<T> { }
|
||||
)
|
||||
impl<T: ?Sized> StructuralEq for $t<T> {}
|
||||
};
|
||||
}
|
||||
|
||||
/// Zero-sized type used to mark things that "act like" they own a `T`.
|
||||
|
@ -661,7 +661,7 @@ macro_rules! impls{
|
|||
#[lang = "phantom_data"]
|
||||
#[structural_match]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct PhantomData<T:?Sized>;
|
||||
pub struct PhantomData<T: ?Sized>;
|
||||
|
||||
impls! { PhantomData }
|
||||
|
||||
|
@ -788,5 +788,4 @@ mod copy_impls {
|
|||
// Shared references can be copied, but mutable references *cannot*!
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Copy for &T {}
|
||||
|
||||
}
|
||||
|
|
|
@ -304,14 +304,15 @@ impl<T> MaybeUninit<T> {
|
|||
#[unstable(feature = "maybe_uninit_uninit_array", issue = "none")]
|
||||
#[inline(always)]
|
||||
pub fn uninit_array<const LEN: usize>() -> [Self; LEN] {
|
||||
unsafe {
|
||||
MaybeUninit::<[MaybeUninit<T>; LEN]>::uninit().assume_init()
|
||||
}
|
||||
unsafe { MaybeUninit::<[MaybeUninit<T>; LEN]>::uninit().assume_init() }
|
||||
}
|
||||
|
||||
/// A promotable constant, equivalent to `uninit()`.
|
||||
#[unstable(feature = "internal_uninit_const", issue = "none",
|
||||
reason = "hack to work around promotability")]
|
||||
#[unstable(
|
||||
feature = "internal_uninit_const",
|
||||
issue = "none",
|
||||
reason = "hack to work around promotability"
|
||||
)]
|
||||
pub const UNINIT: Self = Self::uninit();
|
||||
|
||||
/// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being
|
||||
|
|
|
@ -745,7 +745,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
|
|||
/// [`Copy`]: ../../std/marker/trait.Copy.html
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn drop<T>(_x: T) { }
|
||||
pub fn drop<T>(_x: T) {}
|
||||
|
||||
/// Interprets `src` as having type `&U`, and then reads `src` without moving
|
||||
/// the contained value.
|
||||
|
@ -834,9 +834,7 @@ impl<T> hash::Hash for Discriminant<T> {
|
|||
#[stable(feature = "discriminant_value", since = "1.21.0")]
|
||||
impl<T> fmt::Debug for Discriminant<T> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_tuple("Discriminant")
|
||||
.field(&self.0)
|
||||
.finish()
|
||||
fmt.debug_tuple("Discriminant").field(&self.0).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -342,7 +342,7 @@ impl f32 {
|
|||
///
|
||||
/// assert!(abs_difference <= f32::EPSILON);
|
||||
/// ```
|
||||
#[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
|
||||
#[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")]
|
||||
#[inline]
|
||||
pub fn to_degrees(self) -> f32 {
|
||||
// Use a constant for better precision.
|
||||
|
@ -361,7 +361,7 @@ impl f32 {
|
|||
///
|
||||
/// assert!(abs_difference <= f32::EPSILON);
|
||||
/// ```
|
||||
#[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
|
||||
#[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")]
|
||||
#[inline]
|
||||
pub fn to_radians(self) -> f32 {
|
||||
let value: f32 = consts::PI;
|
||||
|
@ -424,7 +424,10 @@ impl f32 {
|
|||
/// * Be representable in the return type `Int`, after truncating off its fractional part
|
||||
#[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
|
||||
#[inline]
|
||||
pub unsafe fn approx_unchecked_to<Int>(self) -> Int where Self: FloatToInt<Int> {
|
||||
pub unsafe fn approx_unchecked_to<Int>(self) -> Int
|
||||
where
|
||||
Self: FloatToInt<Int>,
|
||||
{
|
||||
FloatToInt::<Int>::approx_unchecked(self)
|
||||
}
|
||||
|
||||
|
|
|
@ -37,10 +37,12 @@ pub struct PanicInfo<'a> {
|
|||
}
|
||||
|
||||
impl<'a> PanicInfo<'a> {
|
||||
#[unstable(feature = "panic_internals",
|
||||
reason = "internal details of the implementation of the `panic!` \
|
||||
#[unstable(
|
||||
feature = "panic_internals",
|
||||
reason = "internal details of the implementation of the `panic!` \
|
||||
and related macros",
|
||||
issue = "none")]
|
||||
issue = "none"
|
||||
)]
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
pub fn internal_constructor(
|
||||
|
@ -48,17 +50,15 @@ impl<'a> PanicInfo<'a> {
|
|||
location: &'a Location<'a>,
|
||||
) -> Self {
|
||||
struct NoPayload;
|
||||
PanicInfo {
|
||||
location,
|
||||
message,
|
||||
payload: &NoPayload,
|
||||
}
|
||||
PanicInfo { location, message, payload: &NoPayload }
|
||||
}
|
||||
|
||||
#[unstable(feature = "panic_internals",
|
||||
reason = "internal details of the implementation of the `panic!` \
|
||||
#[unstable(
|
||||
feature = "panic_internals",
|
||||
reason = "internal details of the implementation of the `panic!` \
|
||||
and related macros",
|
||||
issue = "none")]
|
||||
issue = "none"
|
||||
)]
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) {
|
||||
|
@ -222,9 +222,11 @@ impl<'a> Location<'a> {
|
|||
/// assert_ne!(this_location.line(), another_location.line());
|
||||
/// assert_ne!(this_location.column(), another_location.column());
|
||||
/// ```
|
||||
#[unstable(feature = "track_caller",
|
||||
reason = "uses #[track_caller] which is not yet stable",
|
||||
issue = "47809")]
|
||||
#[unstable(
|
||||
feature = "track_caller",
|
||||
reason = "uses #[track_caller] which is not yet stable",
|
||||
issue = "47809"
|
||||
)]
|
||||
#[track_caller]
|
||||
pub const fn caller() -> &'static Location<'static> {
|
||||
crate::intrinsics::caller_location()
|
||||
|
@ -232,10 +234,12 @@ impl<'a> Location<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Location<'a> {
|
||||
#![unstable(feature = "panic_internals",
|
||||
reason = "internal details of the implementation of the `panic!` \
|
||||
#![unstable(
|
||||
feature = "panic_internals",
|
||||
reason = "internal details of the implementation of the `panic!` \
|
||||
and related macros",
|
||||
issue = "none")]
|
||||
issue = "none"
|
||||
)]
|
||||
#[doc(hidden)]
|
||||
pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
|
||||
Location { file, line, col }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::cmp::Ordering::{self, Less, Equal, Greater};
|
||||
use super::*;
|
||||
use crate::cmp::Ordering::{self, Equal, Greater, Less};
|
||||
use crate::intrinsics;
|
||||
use crate::mem;
|
||||
use super::*;
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
|
@ -154,8 +154,8 @@ impl<T: ?Sized> *const T {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub unsafe fn offset(self, count: isize) -> *const T
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
intrinsics::offset(self, count)
|
||||
}
|
||||
|
@ -212,8 +212,8 @@ impl<T: ?Sized> *const T {
|
|||
#[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
|
||||
#[inline]
|
||||
pub fn wrapping_offset(self, count: isize) -> *const T
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
unsafe { intrinsics::arith_offset(self, count) }
|
||||
}
|
||||
|
@ -284,8 +284,8 @@ impl<T: ?Sized> *const T {
|
|||
#[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
|
||||
#[inline]
|
||||
pub const unsafe fn offset_from(self, origin: *const T) -> isize
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
let pointee_size = mem::size_of::<T>();
|
||||
let ok = 0 < pointee_size && pointee_size <= isize::max_value() as usize;
|
||||
|
@ -332,8 +332,8 @@ impl<T: ?Sized> *const T {
|
|||
#[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
|
||||
#[inline]
|
||||
pub fn wrapping_offset_from(self, origin: *const T) -> isize
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
let pointee_size = mem::size_of::<T>();
|
||||
assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize);
|
||||
|
@ -396,8 +396,8 @@ impl<T: ?Sized> *const T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn add(self, count: usize) -> Self
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
self.offset(count as isize)
|
||||
}
|
||||
|
@ -457,8 +457,8 @@ impl<T: ?Sized> *const T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn sub(self, count: usize) -> Self
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
self.offset((count as isize).wrapping_neg())
|
||||
}
|
||||
|
@ -512,8 +512,8 @@ impl<T: ?Sized> *const T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub fn wrapping_add(self, count: usize) -> Self
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
self.wrapping_offset(count as isize)
|
||||
}
|
||||
|
@ -567,8 +567,8 @@ impl<T: ?Sized> *const T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub fn wrapping_sub(self, count: usize) -> Self
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
self.wrapping_offset((count as isize).wrapping_neg())
|
||||
}
|
||||
|
@ -582,8 +582,8 @@ impl<T: ?Sized> *const T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn read(self) -> T
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
read(self)
|
||||
}
|
||||
|
@ -601,8 +601,8 @@ impl<T: ?Sized> *const T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn read_volatile(self) -> T
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
read_volatile(self)
|
||||
}
|
||||
|
@ -618,8 +618,8 @@ impl<T: ?Sized> *const T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn read_unaligned(self) -> T
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
read_unaligned(self)
|
||||
}
|
||||
|
@ -635,8 +635,8 @@ impl<T: ?Sized> *const T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn copy_to(self, dest: *mut T, count: usize)
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
copy(self, dest, count)
|
||||
}
|
||||
|
@ -652,8 +652,8 @@ impl<T: ?Sized> *const T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
copy_nonoverlapping(self, dest, count)
|
||||
}
|
||||
|
@ -699,8 +699,8 @@ impl<T: ?Sized> *const T {
|
|||
/// ```
|
||||
#[stable(feature = "align_offset", since = "1.36.0")]
|
||||
pub fn align_offset(self, align: usize) -> usize
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
if !align.is_power_of_two() {
|
||||
panic!("align_offset: align is not a power-of-two");
|
||||
|
@ -713,7 +713,9 @@ impl<T: ?Sized> *const T {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> PartialEq for *const T {
|
||||
#[inline]
|
||||
fn eq(&self, other: &*const T) -> bool { *self == *other }
|
||||
fn eq(&self, other: &*const T) -> bool {
|
||||
*self == *other
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -742,14 +744,22 @@ impl<T: ?Sized> PartialOrd for *const T {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn lt(&self, other: &*const T) -> bool { *self < *other }
|
||||
fn lt(&self, other: &*const T) -> bool {
|
||||
*self < *other
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn le(&self, other: &*const T) -> bool { *self <= *other }
|
||||
fn le(&self, other: &*const T) -> bool {
|
||||
*self <= *other
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn gt(&self, other: &*const T) -> bool { *self > *other }
|
||||
fn gt(&self, other: &*const T) -> bool {
|
||||
*self > *other
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn ge(&self, other: &*const T) -> bool { *self >= *other }
|
||||
fn ge(&self, other: &*const T) -> bool {
|
||||
*self >= *other
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,11 +69,11 @@
|
|||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::intrinsics;
|
||||
use crate::cmp::Ordering;
|
||||
use crate::fmt;
|
||||
use crate::hash;
|
||||
use crate::intrinsics;
|
||||
use crate::mem::{self, MaybeUninit};
|
||||
use crate::cmp::Ordering;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use crate::intrinsics::copy_nonoverlapping;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::cmp::Ordering::{self, Less, Equal, Greater};
|
||||
use crate::intrinsics;
|
||||
use super::*;
|
||||
use crate::cmp::Ordering::{self, Equal, Greater, Less};
|
||||
use crate::intrinsics;
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
|
@ -148,8 +148,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub unsafe fn offset(self, count: isize) -> *mut T
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
intrinsics::offset(self, count) as *mut T
|
||||
}
|
||||
|
@ -205,8 +205,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
|
||||
#[inline]
|
||||
pub fn wrapping_offset(self, count: isize) -> *mut T
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
unsafe { intrinsics::arith_offset(self, count) as *mut T }
|
||||
}
|
||||
|
@ -322,8 +322,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
|
||||
#[inline]
|
||||
pub const unsafe fn offset_from(self, origin: *const T) -> isize
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
(self as *const T).offset_from(origin)
|
||||
}
|
||||
|
@ -365,8 +365,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
|
||||
#[inline]
|
||||
pub fn wrapping_offset_from(self, origin: *const T) -> isize
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
(self as *const T).wrapping_offset_from(origin)
|
||||
}
|
||||
|
@ -425,8 +425,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn add(self, count: usize) -> Self
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
self.offset(count as isize)
|
||||
}
|
||||
|
@ -486,8 +486,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn sub(self, count: usize) -> Self
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
self.offset((count as isize).wrapping_neg())
|
||||
}
|
||||
|
@ -541,8 +541,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub fn wrapping_add(self, count: usize) -> Self
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
self.wrapping_offset(count as isize)
|
||||
}
|
||||
|
@ -596,8 +596,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub fn wrapping_sub(self, count: usize) -> Self
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
self.wrapping_offset((count as isize).wrapping_neg())
|
||||
}
|
||||
|
@ -611,8 +611,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn read(self) -> T
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
read(self)
|
||||
}
|
||||
|
@ -630,8 +630,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn read_volatile(self) -> T
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
read_volatile(self)
|
||||
}
|
||||
|
@ -647,8 +647,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn read_unaligned(self) -> T
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
read_unaligned(self)
|
||||
}
|
||||
|
@ -664,8 +664,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn copy_to(self, dest: *mut T, count: usize)
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
copy(self, dest, count)
|
||||
}
|
||||
|
@ -681,8 +681,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
copy_nonoverlapping(self, dest, count)
|
||||
}
|
||||
|
@ -698,8 +698,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn copy_from(self, src: *const T, count: usize)
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
copy(src, self, count)
|
||||
}
|
||||
|
@ -715,8 +715,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize)
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
copy_nonoverlapping(src, self, count)
|
||||
}
|
||||
|
@ -741,8 +741,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn write(self, val: T)
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
write(self, val)
|
||||
}
|
||||
|
@ -756,8 +756,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn write_bytes(self, val: u8, count: usize)
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
write_bytes(self, val, count)
|
||||
}
|
||||
|
@ -775,8 +775,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn write_volatile(self, val: T)
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
write_volatile(self, val)
|
||||
}
|
||||
|
@ -792,8 +792,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn write_unaligned(self, val: T)
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
write_unaligned(self, val)
|
||||
}
|
||||
|
@ -807,8 +807,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn replace(self, src: T) -> T
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
replace(self, src)
|
||||
}
|
||||
|
@ -823,8 +823,8 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
pub unsafe fn swap(self, with: *mut T)
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
swap(self, with)
|
||||
}
|
||||
|
@ -870,8 +870,8 @@ impl<T: ?Sized> *mut T {
|
|||
/// ```
|
||||
#[stable(feature = "align_offset", since = "1.36.0")]
|
||||
pub fn align_offset(self, align: usize) -> usize
|
||||
where
|
||||
T: Sized,
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
if !align.is_power_of_two() {
|
||||
panic!("align_offset: align is not a power-of-two");
|
||||
|
@ -884,7 +884,9 @@ impl<T: ?Sized> *mut T {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> PartialEq for *mut T {
|
||||
#[inline]
|
||||
fn eq(&self, other: &*mut T) -> bool { *self == *other }
|
||||
fn eq(&self, other: &*mut T) -> bool {
|
||||
*self == *other
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -912,14 +914,22 @@ impl<T: ?Sized> PartialOrd for *mut T {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn lt(&self, other: &*mut T) -> bool { *self < *other }
|
||||
fn lt(&self, other: &*mut T) -> bool {
|
||||
*self < *other
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn le(&self, other: &*mut T) -> bool { *self <= *other }
|
||||
fn le(&self, other: &*mut T) -> bool {
|
||||
*self <= *other
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn gt(&self, other: &*mut T) -> bool { *self > *other }
|
||||
fn gt(&self, other: &*mut T) -> bool {
|
||||
*self > *other
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn ge(&self, other: &*mut T) -> bool { *self >= *other }
|
||||
fn ge(&self, other: &*mut T) -> bool {
|
||||
*self >= *other
|
||||
}
|
||||
}
|
||||
|
|
|
@ -283,7 +283,7 @@ impl<T, E> Result<T, E> {
|
|||
pub fn is_ok(&self) -> bool {
|
||||
match *self {
|
||||
Ok(_) => true,
|
||||
Err(_) => false
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,10 +328,13 @@ impl<T, E> Result<T, E> {
|
|||
#[must_use]
|
||||
#[inline]
|
||||
#[unstable(feature = "option_result_contains", issue = "62358")]
|
||||
pub fn contains<U>(&self, x: &U) -> bool where U: PartialEq<T> {
|
||||
pub fn contains<U>(&self, x: &U) -> bool
|
||||
where
|
||||
U: PartialEq<T>,
|
||||
{
|
||||
match self {
|
||||
Ok(y) => x == y,
|
||||
Err(_) => false
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -354,10 +357,13 @@ impl<T, E> Result<T, E> {
|
|||
#[must_use]
|
||||
#[inline]
|
||||
#[unstable(feature = "result_contains_err", issue = "62358")]
|
||||
pub fn contains_err<F>(&self, f: &F) -> bool where F: PartialEq<E> {
|
||||
pub fn contains_err<F>(&self, f: &F) -> bool
|
||||
where
|
||||
F: PartialEq<E>,
|
||||
{
|
||||
match self {
|
||||
Ok(_) => false,
|
||||
Err(e) => f == e
|
||||
Err(e) => f == e,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -387,7 +393,7 @@ impl<T, E> Result<T, E> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn ok(self) -> Option<T> {
|
||||
match self {
|
||||
Ok(x) => Some(x),
|
||||
Ok(x) => Some(x),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
@ -414,7 +420,7 @@ impl<T, E> Result<T, E> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn err(self) -> Option<E> {
|
||||
match self {
|
||||
Ok(_) => None,
|
||||
Ok(_) => None,
|
||||
Err(x) => Some(x),
|
||||
}
|
||||
}
|
||||
|
@ -507,10 +513,10 @@ impl<T, E> Result<T, E> {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U,E> {
|
||||
pub fn map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U, E> {
|
||||
match self {
|
||||
Ok(t) => Ok(op(t)),
|
||||
Err(e) => Err(e)
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -591,10 +597,10 @@ impl<T, E> Result<T, E> {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn map_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T,F> {
|
||||
pub fn map_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T, F> {
|
||||
match self {
|
||||
Ok(t) => Ok(t),
|
||||
Err(e) => Err(op(e))
|
||||
Err(e) => Err(op(e)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -813,7 +819,7 @@ impl<T, E> Result<T, E> {
|
|||
pub fn unwrap_or(self, optb: T) -> T {
|
||||
match self {
|
||||
Ok(t) => t,
|
||||
Err(_) => optb
|
||||
Err(_) => optb,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -838,7 +844,7 @@ impl<T, E> Result<T, E> {
|
|||
pub fn unwrap_or_else<F: FnOnce(E) -> T>(self, op: F) -> T {
|
||||
match self {
|
||||
Ok(t) => t,
|
||||
Err(e) => op(e)
|
||||
Err(e) => op(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -923,7 +929,6 @@ impl<T: Clone, E> Result<&mut T, E> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T, E: fmt::Debug> Result<T, E> {
|
||||
/// Unwraps a result, yielding the content of an [`Ok`].
|
||||
///
|
||||
|
@ -1100,8 +1105,7 @@ impl<T, E: Deref> Result<T, E> {
|
|||
///
|
||||
/// Leaves the original `Result` in-place, creating a new one containing a reference to the
|
||||
/// `Err` type's `Deref::Target` type.
|
||||
pub fn as_deref_err(&self) -> Result<&T, &E::Target>
|
||||
{
|
||||
pub fn as_deref_err(&self) -> Result<&T, &E::Target> {
|
||||
self.as_ref().map_err(|e| e.deref())
|
||||
}
|
||||
}
|
||||
|
@ -1112,8 +1116,7 @@ impl<T: Deref, E: Deref> Result<T, E> {
|
|||
///
|
||||
/// Leaves the original `Result` in-place, creating a new one containing a reference to both
|
||||
/// the `Ok` and `Err` types' `Deref::Target` types.
|
||||
pub fn as_deref(&self) -> Result<&T::Target, &E::Target>
|
||||
{
|
||||
pub fn as_deref(&self) -> Result<&T::Target, &E::Target> {
|
||||
self.as_ref().map(|t| t.deref()).map_err(|e| e.deref())
|
||||
}
|
||||
}
|
||||
|
@ -1135,8 +1138,7 @@ impl<T, E: DerefMut> Result<T, E> {
|
|||
///
|
||||
/// Leaves the original `Result` in-place, creating a new one containing a mutable reference to
|
||||
/// the `Err` type's `Deref::Target` type.
|
||||
pub fn as_deref_mut_err(&mut self) -> Result<&mut T, &mut E::Target>
|
||||
{
|
||||
pub fn as_deref_mut_err(&mut self) -> Result<&mut T, &mut E::Target> {
|
||||
self.as_mut().map_err(|e| e.deref_mut())
|
||||
}
|
||||
}
|
||||
|
@ -1148,8 +1150,7 @@ impl<T: DerefMut, E: DerefMut> Result<T, E> {
|
|||
///
|
||||
/// Leaves the original `Result` in-place, creating a new one containing a mutable reference to
|
||||
/// both the `Ok` and `Err` types' `Deref::Target` types.
|
||||
pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E::Target>
|
||||
{
|
||||
pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E::Target> {
|
||||
self.as_mut().map(|t| t.deref_mut()).map_err(|e| e.deref_mut())
|
||||
}
|
||||
}
|
||||
|
@ -1212,7 +1213,6 @@ impl<T: Clone, E: Clone> Clone for Result<T, E> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T, E> IntoIterator for Result<T, E> {
|
||||
type Item = T;
|
||||
|
@ -1276,17 +1276,21 @@ impl<'a, T, E> IntoIterator for &'a mut Result<T, E> {
|
|||
/// [`Result::iter`]: enum.Result.html#method.iter
|
||||
#[derive(Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Iter<'a, T: 'a> { inner: Option<&'a T> }
|
||||
pub struct Iter<'a, T: 'a> {
|
||||
inner: Option<&'a T>,
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> Iterator for Iter<'a, T> {
|
||||
type Item = &'a T;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'a T> { self.inner.take() }
|
||||
fn next(&mut self) -> Option<&'a T> {
|
||||
self.inner.take()
|
||||
}
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let n = if self.inner.is_some() {1} else {0};
|
||||
let n = if self.inner.is_some() { 1 } else { 0 };
|
||||
(n, Some(n))
|
||||
}
|
||||
}
|
||||
|
@ -1294,7 +1298,9 @@ impl<'a, T> Iterator for Iter<'a, T> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<&'a T> { self.inner.take() }
|
||||
fn next_back(&mut self) -> Option<&'a T> {
|
||||
self.inner.take()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -1309,7 +1315,9 @@ unsafe impl<A> TrustedLen for Iter<'_, A> {}
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Clone for Iter<'_, T> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self { Iter { inner: self.inner } }
|
||||
fn clone(&self) -> Self {
|
||||
Iter { inner: self.inner }
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over a mutable reference to the [`Ok`] variant of a [`Result`].
|
||||
|
@ -1321,17 +1329,21 @@ impl<T> Clone for Iter<'_, T> {
|
|||
/// [`Result::iter_mut`]: enum.Result.html#method.iter_mut
|
||||
#[derive(Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct IterMut<'a, T: 'a> { inner: Option<&'a mut T> }
|
||||
pub struct IterMut<'a, T: 'a> {
|
||||
inner: Option<&'a mut T>,
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> Iterator for IterMut<'a, T> {
|
||||
type Item = &'a mut T;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'a mut T> { self.inner.take() }
|
||||
fn next(&mut self) -> Option<&'a mut T> {
|
||||
self.inner.take()
|
||||
}
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let n = if self.inner.is_some() {1} else {0};
|
||||
let n = if self.inner.is_some() { 1 } else { 0 };
|
||||
(n, Some(n))
|
||||
}
|
||||
}
|
||||
|
@ -1339,7 +1351,9 @@ impl<'a, T> Iterator for IterMut<'a, T> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<&'a mut T> { self.inner.take() }
|
||||
fn next_back(&mut self) -> Option<&'a mut T> {
|
||||
self.inner.take()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -1364,17 +1378,21 @@ unsafe impl<A> TrustedLen for IterMut<'_, A> {}
|
|||
/// [`IntoIterator`]: ../iter/trait.IntoIterator.html
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct IntoIter<T> { inner: Option<T> }
|
||||
pub struct IntoIter<T> {
|
||||
inner: Option<T>,
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Iterator for IntoIter<T> {
|
||||
type Item = T;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<T> { self.inner.take() }
|
||||
fn next(&mut self) -> Option<T> {
|
||||
self.inner.take()
|
||||
}
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let n = if self.inner.is_some() {1} else {0};
|
||||
let n = if self.inner.is_some() { 1 } else { 0 };
|
||||
(n, Some(n))
|
||||
}
|
||||
}
|
||||
|
@ -1382,7 +1400,9 @@ impl<T> Iterator for IntoIter<T> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> DoubleEndedIterator for IntoIter<T> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<T> { self.inner.take() }
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
self.inner.take()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -1443,7 +1463,7 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
|
|||
/// Since the third element caused an underflow, no further elements were taken,
|
||||
/// so the final value of `shared` is 6 (= `3 + 2 + 1`), not 16.
|
||||
#[inline]
|
||||
fn from_iter<I: IntoIterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {
|
||||
fn from_iter<I: IntoIterator<Item = Result<A, E>>>(iter: I) -> Result<V, E> {
|
||||
// FIXME(#11084): This could be replaced with Iterator::scan when this
|
||||
// performance bug is closed.
|
||||
|
||||
|
@ -1452,7 +1472,7 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
|
|||
}
|
||||
|
||||
#[unstable(feature = "try_trait", issue = "42327")]
|
||||
impl<T,E> ops::Try for Result<T, E> {
|
||||
impl<T, E> ops::Try for Result<T, E> {
|
||||
type Ok = T;
|
||||
type Error = E;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,14 +1,14 @@
|
|||
use crate::char;
|
||||
use crate::str as core_str;
|
||||
use crate::fmt::{self, Write};
|
||||
use crate::mem;
|
||||
use crate::str as core_str;
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
/// Lossy UTF-8 string.
|
||||
#[unstable(feature = "str_internals", issue = "none")]
|
||||
pub struct Utf8Lossy {
|
||||
bytes: [u8]
|
||||
bytes: [u8],
|
||||
}
|
||||
|
||||
impl Utf8Lossy {
|
||||
|
@ -25,7 +25,6 @@ impl Utf8Lossy {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// Iterator over lossy UTF-8 string
|
||||
#[unstable(feature = "str_internals", issue = "none")]
|
||||
#[allow(missing_debug_implementations)]
|
||||
|
@ -65,20 +64,21 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> {
|
|||
i += 1;
|
||||
|
||||
if byte < 128 {
|
||||
|
||||
} else {
|
||||
let w = core_str::utf8_char_width(byte);
|
||||
|
||||
macro_rules! error { () => ({
|
||||
unsafe {
|
||||
let r = Utf8LossyChunk {
|
||||
valid: core_str::from_utf8_unchecked(&self.source[0..i_]),
|
||||
broken: &self.source[i_..i],
|
||||
};
|
||||
self.source = &self.source[i..];
|
||||
return Some(r);
|
||||
}
|
||||
})}
|
||||
macro_rules! error {
|
||||
() => {{
|
||||
unsafe {
|
||||
let r = Utf8LossyChunk {
|
||||
valid: core_str::from_utf8_unchecked(&self.source[0..i_]),
|
||||
broken: &self.source[i_..i],
|
||||
};
|
||||
self.source = &self.source[i..];
|
||||
return Some(r);
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
match w {
|
||||
2 => {
|
||||
|
@ -89,10 +89,10 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> {
|
|||
}
|
||||
3 => {
|
||||
match (byte, safe_get(self.source, i)) {
|
||||
(0xE0, 0xA0 ..= 0xBF) => (),
|
||||
(0xE1 ..= 0xEC, 0x80 ..= 0xBF) => (),
|
||||
(0xED, 0x80 ..= 0x9F) => (),
|
||||
(0xEE ..= 0xEF, 0x80 ..= 0xBF) => (),
|
||||
(0xE0, 0xA0..=0xBF) => (),
|
||||
(0xE1..=0xEC, 0x80..=0xBF) => (),
|
||||
(0xED, 0x80..=0x9F) => (),
|
||||
(0xEE..=0xEF, 0x80..=0xBF) => (),
|
||||
_ => {
|
||||
error!();
|
||||
}
|
||||
|
@ -105,9 +105,9 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> {
|
|||
}
|
||||
4 => {
|
||||
match (byte, safe_get(self.source, i)) {
|
||||
(0xF0, 0x90 ..= 0xBF) => (),
|
||||
(0xF1 ..= 0xF3, 0x80 ..= 0xBF) => (),
|
||||
(0xF4, 0x80 ..= 0x8F) => (),
|
||||
(0xF0, 0x90..=0xBF) => (),
|
||||
(0xF1..=0xF3, 0x80..=0xBF) => (),
|
||||
(0xF4, 0x80..=0x8F) => (),
|
||||
_ => {
|
||||
error!();
|
||||
}
|
||||
|
@ -138,13 +138,12 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl fmt::Display for Utf8Lossy {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// If we're the empty string then our iterator won't actually yield
|
||||
// anything, so perform the formatting manually
|
||||
if self.bytes.is_empty() {
|
||||
return "".fmt(f)
|
||||
return "".fmt(f);
|
||||
}
|
||||
|
||||
for Utf8LossyChunk { valid, broken } in self.chunks() {
|
||||
|
@ -153,7 +152,7 @@ impl fmt::Display for Utf8Lossy {
|
|||
// respect various formatting flags if possible.
|
||||
if valid.len() == self.bytes.len() {
|
||||
assert!(broken.is_empty());
|
||||
return valid.fmt(f)
|
||||
return valid.fmt(f);
|
||||
}
|
||||
|
||||
f.write_str(valid)?;
|
||||
|
@ -170,7 +169,6 @@ impl fmt::Debug for Utf8Lossy {
|
|||
f.write_char('"')?;
|
||||
|
||||
for Utf8LossyChunk { valid, broken } in self.chunks() {
|
||||
|
||||
// Valid part.
|
||||
// Here we partially parse UTF-8 again which is suboptimal.
|
||||
{
|
||||
|
|
|
@ -8,16 +8,16 @@
|
|||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use self::pattern::Pattern;
|
||||
use self::pattern::{Searcher, SearchStep, ReverseSearcher, DoubleEndedSearcher};
|
||||
use self::pattern::{DoubleEndedSearcher, ReverseSearcher, SearchStep, Searcher};
|
||||
|
||||
use crate::char;
|
||||
use crate::fmt::{self, Write};
|
||||
use crate::iter::{Map, Cloned, FusedIterator, TrustedLen, TrustedRandomAccess, Filter};
|
||||
use crate::iter::{Flatten, FlatMap, Chain};
|
||||
use crate::slice::{self, SliceIndex, Split as SliceSplit};
|
||||
use crate::iter::{Chain, FlatMap, Flatten};
|
||||
use crate::iter::{Cloned, Filter, FusedIterator, Map, TrustedLen, TrustedRandomAccess};
|
||||
use crate::mem;
|
||||
use crate::ops::Try;
|
||||
use crate::option;
|
||||
use crate::slice::{self, SliceIndex, Split as SliceSplit};
|
||||
|
||||
pub mod pattern;
|
||||
|
||||
|
@ -133,9 +133,9 @@ impl FromStr for bool {
|
|||
#[inline]
|
||||
fn from_str(s: &str) -> Result<bool, ParseBoolError> {
|
||||
match s {
|
||||
"true" => Ok(true),
|
||||
"true" => Ok(true),
|
||||
"false" => Ok(false),
|
||||
_ => Err(ParseBoolError { _priv: () }),
|
||||
_ => Err(ParseBoolError { _priv: () }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +145,9 @@ impl FromStr for bool {
|
|||
/// [`from_str`]: ../../std/primitive.bool.html#method.from_str
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct ParseBoolError { _priv: () }
|
||||
pub struct ParseBoolError {
|
||||
_priv: (),
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Display for ParseBoolError {
|
||||
|
@ -230,7 +232,9 @@ impl Utf8Error {
|
|||
/// assert_eq!(1, error.valid_up_to());
|
||||
/// ```
|
||||
#[stable(feature = "utf8_error", since = "1.5.0")]
|
||||
pub fn valid_up_to(&self) -> usize { self.valid_up_to }
|
||||
pub fn valid_up_to(&self) -> usize {
|
||||
self.valid_up_to
|
||||
}
|
||||
|
||||
/// Provides more information about the failure:
|
||||
///
|
||||
|
@ -444,8 +448,11 @@ pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
|
|||
impl fmt::Display for Utf8Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if let Some(error_len) = self.error_len {
|
||||
write!(f, "invalid utf-8 sequence of {} bytes from index {}",
|
||||
error_len, self.valid_up_to)
|
||||
write!(
|
||||
f,
|
||||
"invalid utf-8 sequence of {} bytes from index {}",
|
||||
error_len, self.valid_up_to
|
||||
)
|
||||
} else {
|
||||
write!(f, "incomplete utf-8 byte sequence from index {}", self.valid_up_to)
|
||||
}
|
||||
|
@ -468,23 +475,29 @@ Section: Iterators
|
|||
#[derive(Clone)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Chars<'a> {
|
||||
iter: slice::Iter<'a, u8>
|
||||
iter: slice::Iter<'a, u8>,
|
||||
}
|
||||
|
||||
/// Returns the initial codepoint accumulator for the first byte.
|
||||
/// The first byte is special, only want bottom 5 bits for width 2, 4 bits
|
||||
/// for width 3, and 3 bits for width 4.
|
||||
#[inline]
|
||||
fn utf8_first_byte(byte: u8, width: u32) -> u32 { (byte & (0x7F >> width)) as u32 }
|
||||
fn utf8_first_byte(byte: u8, width: u32) -> u32 {
|
||||
(byte & (0x7F >> width)) as u32
|
||||
}
|
||||
|
||||
/// Returns the value of `ch` updated with continuation byte `byte`.
|
||||
#[inline]
|
||||
fn utf8_acc_cont_byte(ch: u32, byte: u8) -> u32 { (ch << 6) | (byte & CONT_MASK) as u32 }
|
||||
fn utf8_acc_cont_byte(ch: u32, byte: u8) -> u32 {
|
||||
(ch << 6) | (byte & CONT_MASK) as u32
|
||||
}
|
||||
|
||||
/// Checks whether the byte is a UTF-8 continuation byte (i.e., starts with the
|
||||
/// bits `10`).
|
||||
#[inline]
|
||||
fn utf8_is_cont_byte(byte: u8) -> bool { (byte & !CONT_MASK) == TAG_CONT_U8 }
|
||||
fn utf8_is_cont_byte(byte: u8) -> bool {
|
||||
(byte & !CONT_MASK) == TAG_CONT_U8
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn unwrap_or_0(opt: Option<&u8>) -> u8 {
|
||||
|
@ -502,7 +515,7 @@ pub fn next_code_point<'a, I: Iterator<Item = &'a u8>>(bytes: &mut I) -> Option<
|
|||
// Decode UTF-8
|
||||
let x = *bytes.next()?;
|
||||
if x < 128 {
|
||||
return Some(x as u32)
|
||||
return Some(x as u32);
|
||||
}
|
||||
|
||||
// Multibyte case follows
|
||||
|
@ -532,7 +545,8 @@ pub fn next_code_point<'a, I: Iterator<Item = &'a u8>>(bytes: &mut I) -> Option<
|
|||
/// UTF-8-like encoding).
|
||||
#[inline]
|
||||
fn next_code_point_reverse<'a, I>(bytes: &mut I) -> Option<u32>
|
||||
where I: DoubleEndedIterator<Item = &'a u8>,
|
||||
where
|
||||
I: DoubleEndedIterator<Item = &'a u8>,
|
||||
{
|
||||
// Decode UTF-8
|
||||
let w = match *bytes.next_back()? {
|
||||
|
@ -568,9 +582,7 @@ impl<'a> Iterator for Chars<'a> {
|
|||
fn next(&mut self) -> Option<char> {
|
||||
next_code_point(&mut self.iter).map(|ch| {
|
||||
// str invariant says `ch` is a valid Unicode Scalar Value
|
||||
unsafe {
|
||||
char::from_u32_unchecked(ch)
|
||||
}
|
||||
unsafe { char::from_u32_unchecked(ch) }
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -617,9 +629,7 @@ impl<'a> DoubleEndedIterator for Chars<'a> {
|
|||
fn next_back(&mut self) -> Option<char> {
|
||||
next_code_point_reverse(&mut self.iter).map(|ch| {
|
||||
// str invariant says `ch` is a valid Unicode Scalar Value
|
||||
unsafe {
|
||||
char::from_u32_unchecked(ch)
|
||||
}
|
||||
unsafe { char::from_u32_unchecked(ch) }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -770,32 +780,41 @@ impl Iterator for Bytes<'_> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn all<F>(&mut self, f: F) -> bool where F: FnMut(Self::Item) -> bool {
|
||||
fn all<F>(&mut self, f: F) -> bool
|
||||
where
|
||||
F: FnMut(Self::Item) -> bool,
|
||||
{
|
||||
self.0.all(f)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn any<F>(&mut self, f: F) -> bool where F: FnMut(Self::Item) -> bool {
|
||||
fn any<F>(&mut self, f: F) -> bool
|
||||
where
|
||||
F: FnMut(Self::Item) -> bool,
|
||||
{
|
||||
self.0.any(f)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where
|
||||
P: FnMut(&Self::Item) -> bool
|
||||
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
self.0.find(predicate)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn position<P>(&mut self, predicate: P) -> Option<usize> where
|
||||
P: FnMut(Self::Item) -> bool
|
||||
fn position<P>(&mut self, predicate: P) -> Option<usize>
|
||||
where
|
||||
P: FnMut(Self::Item) -> bool,
|
||||
{
|
||||
self.0.position(predicate)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rposition<P>(&mut self, predicate: P) -> Option<usize> where
|
||||
P: FnMut(Self::Item) -> bool
|
||||
fn rposition<P>(&mut self, predicate: P) -> Option<usize>
|
||||
where
|
||||
P: FnMut(Self::Item) -> bool,
|
||||
{
|
||||
self.0.rposition(predicate)
|
||||
}
|
||||
|
@ -814,8 +833,9 @@ impl DoubleEndedIterator for Bytes<'_> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> where
|
||||
P: FnMut(&Self::Item) -> bool
|
||||
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
self.0.rfind(predicate)
|
||||
}
|
||||
|
@ -845,7 +865,9 @@ unsafe impl TrustedRandomAccess for Bytes<'_> {
|
|||
unsafe fn get_unchecked(&mut self, i: usize) -> u8 {
|
||||
self.0.get_unchecked(i)
|
||||
}
|
||||
fn may_have_side_effect() -> bool { false }
|
||||
fn may_have_side_effect() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// This macro generates a Clone impl for string pattern API
|
||||
|
@ -861,7 +883,7 @@ macro_rules! derive_pattern_clone {
|
|||
$e
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// This macro generates two public iterator structs
|
||||
|
@ -1047,7 +1069,7 @@ macro_rules! generate_pattern_iterators {
|
|||
} => {}
|
||||
}
|
||||
|
||||
derive_pattern_clone!{
|
||||
derive_pattern_clone! {
|
||||
clone SplitInternal
|
||||
with |s| SplitInternal { matcher: s.matcher.clone(), ..*s }
|
||||
}
|
||||
|
@ -1091,7 +1113,9 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
|
|||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'a str> {
|
||||
if self.finished { return None }
|
||||
if self.finished {
|
||||
return None;
|
||||
}
|
||||
|
||||
let haystack = self.matcher.haystack();
|
||||
match self.matcher.next_match() {
|
||||
|
@ -1106,15 +1130,22 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
|
|||
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<&'a str>
|
||||
where P::Searcher: ReverseSearcher<'a>
|
||||
where
|
||||
P::Searcher: ReverseSearcher<'a>,
|
||||
{
|
||||
if self.finished { return None }
|
||||
if self.finished {
|
||||
return None;
|
||||
}
|
||||
|
||||
if !self.allow_trailing_empty {
|
||||
self.allow_trailing_empty = true;
|
||||
match self.next_back() {
|
||||
Some(elt) if !elt.is_empty() => return Some(elt),
|
||||
_ => if self.finished { return None }
|
||||
_ => {
|
||||
if self.finished {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1169,7 +1200,7 @@ generate_pattern_iterators! {
|
|||
delegate double ended;
|
||||
}
|
||||
|
||||
derive_pattern_clone!{
|
||||
derive_pattern_clone! {
|
||||
clone SplitNInternal
|
||||
with |s| SplitNInternal { iter: s.iter.clone(), ..*s }
|
||||
}
|
||||
|
@ -1197,19 +1228,32 @@ impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> {
|
|||
fn next(&mut self) -> Option<&'a str> {
|
||||
match self.count {
|
||||
0 => None,
|
||||
1 => { self.count = 0; self.iter.get_end() }
|
||||
_ => { self.count -= 1; self.iter.next() }
|
||||
1 => {
|
||||
self.count = 0;
|
||||
self.iter.get_end()
|
||||
}
|
||||
_ => {
|
||||
self.count -= 1;
|
||||
self.iter.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<&'a str>
|
||||
where P::Searcher: ReverseSearcher<'a>
|
||||
where
|
||||
P::Searcher: ReverseSearcher<'a>,
|
||||
{
|
||||
match self.count {
|
||||
0 => None,
|
||||
1 => { self.count = 0; self.iter.get_end() }
|
||||
_ => { self.count -= 1; self.iter.next_back() }
|
||||
1 => {
|
||||
self.count = 0;
|
||||
self.iter.get_end()
|
||||
}
|
||||
_ => {
|
||||
self.count -= 1;
|
||||
self.iter.next_back()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1232,7 +1276,7 @@ generate_pattern_iterators! {
|
|||
delegate single ended;
|
||||
}
|
||||
|
||||
derive_pattern_clone!{
|
||||
derive_pattern_clone! {
|
||||
clone MatchIndicesInternal
|
||||
with |s| MatchIndicesInternal(s.0.clone())
|
||||
}
|
||||
|
@ -1244,27 +1288,26 @@ where
|
|||
P: Pattern<'a, Searcher: fmt::Debug>,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("MatchIndicesInternal")
|
||||
.field(&self.0)
|
||||
.finish()
|
||||
f.debug_tuple("MatchIndicesInternal").field(&self.0).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<(usize, &'a str)> {
|
||||
self.0.next_match().map(|(start, end)| unsafe {
|
||||
(start, self.0.haystack().get_unchecked(start..end))
|
||||
})
|
||||
self.0
|
||||
.next_match()
|
||||
.map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<(usize, &'a str)>
|
||||
where P::Searcher: ReverseSearcher<'a>
|
||||
where
|
||||
P::Searcher: ReverseSearcher<'a>,
|
||||
{
|
||||
self.0.next_match_back().map(|(start, end)| unsafe {
|
||||
(start, self.0.haystack().get_unchecked(start..end))
|
||||
})
|
||||
self.0
|
||||
.next_match_back()
|
||||
.map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1286,7 +1329,7 @@ generate_pattern_iterators! {
|
|||
delegate double ended;
|
||||
}
|
||||
|
||||
derive_pattern_clone!{
|
||||
derive_pattern_clone! {
|
||||
clone MatchesInternal
|
||||
with |s| MatchesInternal(s.0.clone())
|
||||
}
|
||||
|
@ -1298,9 +1341,7 @@ where
|
|||
P: Pattern<'a, Searcher: fmt::Debug>,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("MatchesInternal")
|
||||
.field(&self.0)
|
||||
.finish()
|
||||
f.debug_tuple("MatchesInternal").field(&self.0).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1315,7 +1356,8 @@ impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> {
|
|||
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<&'a str>
|
||||
where P::Searcher: ReverseSearcher<'a>
|
||||
where
|
||||
P::Searcher: ReverseSearcher<'a>,
|
||||
{
|
||||
self.0.next_match_back().map(|(a, b)| unsafe {
|
||||
// Indices are known to be on utf8 boundaries
|
||||
|
@ -1461,21 +1503,20 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
|
|||
let old_offset = index;
|
||||
macro_rules! err {
|
||||
($error_len: expr) => {
|
||||
return Err(Utf8Error {
|
||||
valid_up_to: old_offset,
|
||||
error_len: $error_len,
|
||||
})
|
||||
}
|
||||
return Err(Utf8Error { valid_up_to: old_offset, error_len: $error_len });
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! next { () => {{
|
||||
index += 1;
|
||||
// we needed data, but there was none: error!
|
||||
if index >= len {
|
||||
err!(None)
|
||||
}
|
||||
v[index]
|
||||
}}}
|
||||
macro_rules! next {
|
||||
() => {{
|
||||
index += 1;
|
||||
// we needed data, but there was none: error!
|
||||
if index >= len {
|
||||
err!(None)
|
||||
}
|
||||
v[index]
|
||||
}};
|
||||
}
|
||||
|
||||
let first = v[index];
|
||||
if first >= 128 {
|
||||
|
@ -1499,16 +1540,18 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
|
|||
// UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
|
||||
// %xF4 %x80-8F 2( UTF8-tail )
|
||||
match w {
|
||||
2 => if next!() & !CONT_MASK != TAG_CONT_U8 {
|
||||
err!(Some(1))
|
||||
},
|
||||
2 => {
|
||||
if next!() & !CONT_MASK != TAG_CONT_U8 {
|
||||
err!(Some(1))
|
||||
}
|
||||
}
|
||||
3 => {
|
||||
match (first, next!()) {
|
||||
(0xE0 , 0xA0 ..= 0xBF) |
|
||||
(0xE1 ..= 0xEC, 0x80 ..= 0xBF) |
|
||||
(0xED , 0x80 ..= 0x9F) |
|
||||
(0xEE ..= 0xEF, 0x80 ..= 0xBF) => {}
|
||||
_ => err!(Some(1))
|
||||
(0xE0, 0xA0..=0xBF)
|
||||
| (0xE1..=0xEC, 0x80..=0xBF)
|
||||
| (0xED, 0x80..=0x9F)
|
||||
| (0xEE..=0xEF, 0x80..=0xBF) => {}
|
||||
_ => err!(Some(1)),
|
||||
}
|
||||
if next!() & !CONT_MASK != TAG_CONT_U8 {
|
||||
err!(Some(2))
|
||||
|
@ -1516,10 +1559,8 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
|
|||
}
|
||||
4 => {
|
||||
match (first, next!()) {
|
||||
(0xF0 , 0x90 ..= 0xBF) |
|
||||
(0xF1 ..= 0xF3, 0x80 ..= 0xBF) |
|
||||
(0xF4 , 0x80 ..= 0x8F) => {}
|
||||
_ => err!(Some(1))
|
||||
(0xF0, 0x90..=0xBF) | (0xF1..=0xF3, 0x80..=0xBF) | (0xF4, 0x80..=0x8F) => {}
|
||||
_ => err!(Some(1)),
|
||||
}
|
||||
if next!() & !CONT_MASK != TAG_CONT_U8 {
|
||||
err!(Some(2))
|
||||
|
@ -1528,7 +1569,7 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
|
|||
err!(Some(3))
|
||||
}
|
||||
}
|
||||
_ => err!(Some(1))
|
||||
_ => err!(Some(1)),
|
||||
}
|
||||
index += 1;
|
||||
} else {
|
||||
|
@ -1564,22 +1605,22 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
|
|||
|
||||
// https://tools.ietf.org/html/rfc3629
|
||||
static UTF8_CHAR_WIDTH: [u8; 256] = [
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x3F
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x5F
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x7F
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x9F
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xBF
|
||||
0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xDF
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 0xEF
|
||||
4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, // 0xFF
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, // 0x1F
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, // 0x3F
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, // 0x5F
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, // 0x7F
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, // 0x9F
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, // 0xBF
|
||||
0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, // 0xDF
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEF
|
||||
4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xFF
|
||||
];
|
||||
|
||||
/// Given a first byte, determines how many bytes are in this UTF-8 character.
|
||||
|
@ -1625,7 +1666,9 @@ mod traits {
|
|||
self.as_bytes() == other.as_bytes()
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &str) -> bool { !(*self).eq(other) }
|
||||
fn ne(&self, other: &str) -> bool {
|
||||
!(*self).eq(other)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -1757,9 +1800,10 @@ mod traits {
|
|||
type Output = str;
|
||||
#[inline]
|
||||
fn get(self, slice: &str) -> Option<&Self::Output> {
|
||||
if self.start <= self.end &&
|
||||
slice.is_char_boundary(self.start) &&
|
||||
slice.is_char_boundary(self.end) {
|
||||
if self.start <= self.end
|
||||
&& slice.is_char_boundary(self.start)
|
||||
&& slice.is_char_boundary(self.end)
|
||||
{
|
||||
Some(unsafe { self.get_unchecked(slice) })
|
||||
} else {
|
||||
None
|
||||
|
@ -1767,9 +1811,10 @@ mod traits {
|
|||
}
|
||||
#[inline]
|
||||
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
|
||||
if self.start <= self.end &&
|
||||
slice.is_char_boundary(self.start) &&
|
||||
slice.is_char_boundary(self.end) {
|
||||
if self.start <= self.end
|
||||
&& slice.is_char_boundary(self.start)
|
||||
&& slice.is_char_boundary(self.end)
|
||||
{
|
||||
Some(unsafe { self.get_unchecked_mut(slice) })
|
||||
} else {
|
||||
None
|
||||
|
@ -1796,9 +1841,10 @@ mod traits {
|
|||
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
// is_char_boundary checks that the index is in [0, .len()]
|
||||
// cannot reuse `get` as above, because of NLL trouble
|
||||
if self.start <= self.end &&
|
||||
slice.is_char_boundary(self.start) &&
|
||||
slice.is_char_boundary(self.end) {
|
||||
if self.start <= self.end
|
||||
&& slice.is_char_boundary(self.start)
|
||||
&& slice.is_char_boundary(self.end)
|
||||
{
|
||||
unsafe { self.get_unchecked_mut(slice) }
|
||||
} else {
|
||||
super::slice_error_fail(slice, self.start, self.end)
|
||||
|
@ -1950,31 +1996,41 @@ mod traits {
|
|||
type Output = str;
|
||||
#[inline]
|
||||
fn get(self, slice: &str) -> Option<&Self::Output> {
|
||||
if *self.end() == usize::max_value() { None }
|
||||
else { (*self.start()..self.end()+1).get(slice) }
|
||||
if *self.end() == usize::max_value() {
|
||||
None
|
||||
} else {
|
||||
(*self.start()..self.end() + 1).get(slice)
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
|
||||
if *self.end() == usize::max_value() { None }
|
||||
else { (*self.start()..self.end()+1).get_mut(slice) }
|
||||
if *self.end() == usize::max_value() {
|
||||
None
|
||||
} else {
|
||||
(*self.start()..self.end() + 1).get_mut(slice)
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
|
||||
(*self.start()..self.end()+1).get_unchecked(slice)
|
||||
(*self.start()..self.end() + 1).get_unchecked(slice)
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
(*self.start()..self.end()+1).get_unchecked_mut(slice)
|
||||
(*self.start()..self.end() + 1).get_unchecked_mut(slice)
|
||||
}
|
||||
#[inline]
|
||||
fn index(self, slice: &str) -> &Self::Output {
|
||||
if *self.end() == usize::max_value() { str_index_overflow_fail(); }
|
||||
(*self.start()..self.end()+1).index(slice)
|
||||
if *self.end() == usize::max_value() {
|
||||
str_index_overflow_fail();
|
||||
}
|
||||
(*self.start()..self.end() + 1).index(slice)
|
||||
}
|
||||
#[inline]
|
||||
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
if *self.end() == usize::max_value() { str_index_overflow_fail(); }
|
||||
(*self.start()..self.end()+1).index_mut(slice)
|
||||
if *self.end() == usize::max_value() {
|
||||
str_index_overflow_fail();
|
||||
}
|
||||
(*self.start()..self.end() + 1).index_mut(slice)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1997,31 +2053,33 @@ mod traits {
|
|||
type Output = str;
|
||||
#[inline]
|
||||
fn get(self, slice: &str) -> Option<&Self::Output> {
|
||||
if self.end == usize::max_value() { None }
|
||||
else { (..self.end+1).get(slice) }
|
||||
if self.end == usize::max_value() { None } else { (..self.end + 1).get(slice) }
|
||||
}
|
||||
#[inline]
|
||||
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
|
||||
if self.end == usize::max_value() { None }
|
||||
else { (..self.end+1).get_mut(slice) }
|
||||
if self.end == usize::max_value() { None } else { (..self.end + 1).get_mut(slice) }
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
|
||||
(..self.end+1).get_unchecked(slice)
|
||||
(..self.end + 1).get_unchecked(slice)
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
(..self.end+1).get_unchecked_mut(slice)
|
||||
(..self.end + 1).get_unchecked_mut(slice)
|
||||
}
|
||||
#[inline]
|
||||
fn index(self, slice: &str) -> &Self::Output {
|
||||
if self.end == usize::max_value() { str_index_overflow_fail(); }
|
||||
(..self.end+1).index(slice)
|
||||
if self.end == usize::max_value() {
|
||||
str_index_overflow_fail();
|
||||
}
|
||||
(..self.end + 1).index(slice)
|
||||
}
|
||||
#[inline]
|
||||
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
if self.end == usize::max_value() { str_index_overflow_fail(); }
|
||||
(..self.end+1).index_mut(slice)
|
||||
if self.end == usize::max_value() {
|
||||
str_index_overflow_fail();
|
||||
}
|
||||
(..self.end + 1).index_mut(slice)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2053,8 +2111,14 @@ fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
|
|||
}
|
||||
|
||||
// 2. begin <= end
|
||||
assert!(begin <= end, "begin <= end ({} <= {}) when slicing `{}`{}",
|
||||
begin, end, s_trunc, ellipsis);
|
||||
assert!(
|
||||
begin <= end,
|
||||
"begin <= end ({} <= {}) when slicing `{}`{}",
|
||||
begin,
|
||||
end,
|
||||
s_trunc,
|
||||
ellipsis
|
||||
);
|
||||
|
||||
// 3. character boundary
|
||||
let index = if !s.is_char_boundary(begin) { begin } else { end };
|
||||
|
@ -2065,9 +2129,11 @@ fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
|
|||
}
|
||||
// `char_start` must be less than len and a char boundary
|
||||
let ch = s[char_start..].chars().next().unwrap();
|
||||
let char_range = char_start .. char_start + ch.len_utf8();
|
||||
panic!("byte index {} is not a char boundary; it is inside {:?} (bytes {:?}) of `{}`{}",
|
||||
index, ch, char_range, s_trunc, ellipsis);
|
||||
let char_range = char_start..char_start + ch.len_utf8();
|
||||
panic!(
|
||||
"byte index {} is not a char boundary; it is inside {:?} (bytes {:?}) of `{}`{}",
|
||||
index, ch, char_range, s_trunc, ellipsis
|
||||
);
|
||||
}
|
||||
|
||||
#[lang = "str"]
|
||||
|
@ -2146,7 +2212,9 @@ impl str {
|
|||
// 0 and len are always ok.
|
||||
// Test for 0 explicitly so that it can optimize out the check
|
||||
// easily and skip reading string data for that case.
|
||||
if index == 0 || index == self.len() { return true; }
|
||||
if index == 0 || index == self.len() {
|
||||
return true;
|
||||
}
|
||||
match self.as_bytes().get(index) {
|
||||
None => false,
|
||||
// This is bit magic equivalent to: b < 128 || b >= 192
|
||||
|
@ -2505,10 +2573,7 @@ impl str {
|
|||
pub fn split_at(&self, mid: usize) -> (&str, &str) {
|
||||
// is_char_boundary checks that the index is in [0, .len()]
|
||||
if self.is_char_boundary(mid) {
|
||||
unsafe {
|
||||
(self.get_unchecked(0..mid),
|
||||
self.get_unchecked(mid..self.len()))
|
||||
}
|
||||
unsafe { (self.get_unchecked(0..mid), self.get_unchecked(mid..self.len())) }
|
||||
} else {
|
||||
slice_error_fail(self, 0, mid)
|
||||
}
|
||||
|
@ -2553,11 +2618,10 @@ impl str {
|
|||
let len = self.len();
|
||||
let ptr = self.as_mut_ptr();
|
||||
unsafe {
|
||||
(from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, mid)),
|
||||
from_utf8_unchecked_mut(slice::from_raw_parts_mut(
|
||||
ptr.add(mid),
|
||||
len - mid
|
||||
)))
|
||||
(
|
||||
from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, mid)),
|
||||
from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr.add(mid), len - mid)),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
slice_error_fail(self, 0, mid)
|
||||
|
@ -2611,7 +2675,7 @@ impl str {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn chars(&self) -> Chars<'_> {
|
||||
Chars{iter: self.as_bytes().iter()}
|
||||
Chars { iter: self.as_bytes().iter() }
|
||||
}
|
||||
|
||||
/// Returns an iterator over the [`char`]s of a string slice, and their
|
||||
|
@ -2775,11 +2839,8 @@ impl str {
|
|||
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
|
||||
#[inline]
|
||||
pub fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_> {
|
||||
let inner = self
|
||||
.as_bytes()
|
||||
.split(IsAsciiWhitespace)
|
||||
.filter(BytesIsNotEmpty)
|
||||
.map(UnsafeBytesToStr);
|
||||
let inner =
|
||||
self.as_bytes().split(IsAsciiWhitespace).filter(BytesIsNotEmpty).map(UnsafeBytesToStr);
|
||||
SplitAsciiWhitespace { inner }
|
||||
}
|
||||
|
||||
|
@ -3220,10 +3281,7 @@ impl str {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
|
||||
SplitTerminator(SplitInternal {
|
||||
allow_trailing_empty: false,
|
||||
..self.split(pat).0
|
||||
})
|
||||
SplitTerminator(SplitInternal { allow_trailing_empty: false, ..self.split(pat).0 })
|
||||
}
|
||||
|
||||
/// An iterator over substrings of `self`, separated by characters
|
||||
|
@ -3317,10 +3375,7 @@ impl str {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> {
|
||||
SplitN(SplitNInternal {
|
||||
iter: self.split(pat).0,
|
||||
count: n,
|
||||
})
|
||||
SplitN(SplitNInternal { iter: self.split(pat).0, count: n })
|
||||
}
|
||||
|
||||
/// An iterator over substrings of this string slice, separated by a
|
||||
|
@ -3662,7 +3717,7 @@ impl str {
|
|||
#[rustc_deprecated(
|
||||
since = "1.33.0",
|
||||
reason = "superseded by `trim_start`",
|
||||
suggestion = "trim_start",
|
||||
suggestion = "trim_start"
|
||||
)]
|
||||
pub fn trim_left(&self) -> &str {
|
||||
self.trim_start()
|
||||
|
@ -3703,7 +3758,7 @@ impl str {
|
|||
#[rustc_deprecated(
|
||||
since = "1.33.0",
|
||||
reason = "superseded by `trim_end`",
|
||||
suggestion = "trim_end",
|
||||
suggestion = "trim_end"
|
||||
)]
|
||||
pub fn trim_right(&self) -> &str {
|
||||
self.trim_end()
|
||||
|
@ -3745,7 +3800,7 @@ impl str {
|
|||
if let Some((a, b)) = matcher.next_reject() {
|
||||
i = a;
|
||||
j = b; // Remember earliest known match, correct it below if
|
||||
// last match is different
|
||||
// last match is different
|
||||
}
|
||||
if let Some((_, b)) = matcher.next_reject_back() {
|
||||
j = b;
|
||||
|
@ -3818,8 +3873,11 @@ impl str {
|
|||
pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a str> {
|
||||
let mut matcher = prefix.into_searcher(self);
|
||||
if let SearchStep::Match(start, len) = matcher.next() {
|
||||
debug_assert_eq!(start, 0, "The first search step from Searcher \
|
||||
must include the first character");
|
||||
debug_assert_eq!(
|
||||
start, 0,
|
||||
"The first search step from Searcher \
|
||||
must include the first character"
|
||||
);
|
||||
unsafe {
|
||||
// Searcher is known to return valid indices.
|
||||
Some(self.get_unchecked(len..))
|
||||
|
@ -3855,8 +3913,12 @@ impl str {
|
|||
{
|
||||
let mut matcher = suffix.into_searcher(self);
|
||||
if let SearchStep::Match(start, end) = matcher.next_back() {
|
||||
debug_assert_eq!(end, self.len(), "The first search step from ReverseSearcher \
|
||||
must include the last character");
|
||||
debug_assert_eq!(
|
||||
end,
|
||||
self.len(),
|
||||
"The first search step from ReverseSearcher \
|
||||
must include the last character"
|
||||
);
|
||||
unsafe {
|
||||
// Searcher is known to return valid indices.
|
||||
Some(self.get_unchecked(..start))
|
||||
|
@ -3944,7 +4006,7 @@ impl str {
|
|||
#[rustc_deprecated(
|
||||
since = "1.33.0",
|
||||
reason = "superseded by `trim_start_matches`",
|
||||
suggestion = "trim_start_matches",
|
||||
suggestion = "trim_start_matches"
|
||||
)]
|
||||
pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
|
||||
self.trim_start_matches(pat)
|
||||
|
@ -3986,7 +4048,7 @@ impl str {
|
|||
#[rustc_deprecated(
|
||||
since = "1.33.0",
|
||||
reason = "superseded by `trim_end_matches`",
|
||||
suggestion = "trim_end_matches",
|
||||
suggestion = "trim_end_matches"
|
||||
)]
|
||||
pub fn trim_right_matches<'a, P>(&'a self, pat: P) -> &'a str
|
||||
where
|
||||
|
@ -4173,11 +4235,12 @@ impl str {
|
|||
pub fn escape_debug(&self) -> EscapeDebug<'_> {
|
||||
let mut chars = self.chars();
|
||||
EscapeDebug {
|
||||
inner: chars.next()
|
||||
inner: chars
|
||||
.next()
|
||||
.map(|first| first.escape_debug_ext(true))
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.chain(chars.flat_map(CharEscapeDebugContinue))
|
||||
.chain(chars.flat_map(CharEscapeDebugContinue)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4285,13 +4348,17 @@ impl AsRef<[u8]> for str {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Default for &str {
|
||||
/// Creates an empty str
|
||||
fn default() -> Self { "" }
|
||||
fn default() -> Self {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "default_mut_str", since = "1.28.0")]
|
||||
impl Default for &mut str {
|
||||
/// Creates an empty mutable str
|
||||
fn default() -> Self { unsafe { from_utf8_unchecked_mut(&mut []) } }
|
||||
fn default() -> Self {
|
||||
unsafe { from_utf8_unchecked_mut(&mut []) }
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the non-whitespace substrings of a string,
|
||||
|
@ -4477,7 +4544,7 @@ impl FusedIterator for EncodeUtf16<'_> {}
|
|||
pub struct EscapeDebug<'a> {
|
||||
inner: Chain<
|
||||
Flatten<option::IntoIter<char::EscapeDebug>>,
|
||||
FlatMap<Chars<'a>, char::EscapeDebug, CharEscapeDebugContinue>
|
||||
FlatMap<Chars<'a>, char::EscapeDebug, CharEscapeDebugContinue>,
|
||||
>,
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
#![unstable(feature = "pattern",
|
||||
reason = "API not fully fleshed out and ready to be stabilized",
|
||||
issue = "27721")]
|
||||
#![unstable(
|
||||
feature = "pattern",
|
||||
reason = "API not fully fleshed out and ready to be stabilized",
|
||||
issue = "27721"
|
||||
)]
|
||||
|
||||
use crate::cmp;
|
||||
use crate::fmt;
|
||||
|
@ -53,7 +55,8 @@ pub trait Pattern<'a>: Sized {
|
|||
/// Checks whether the pattern matches at the back of the haystack
|
||||
#[inline]
|
||||
fn is_suffix_of(self, haystack: &'a str) -> bool
|
||||
where Self::Searcher: ReverseSearcher<'a>
|
||||
where
|
||||
Self::Searcher: ReverseSearcher<'a>,
|
||||
{
|
||||
match self.into_searcher(haystack).next_back() {
|
||||
SearchStep::Match(_, j) if haystack.len() == j => true,
|
||||
|
@ -78,7 +81,7 @@ pub enum SearchStep {
|
|||
Reject(usize, usize),
|
||||
/// Expresses that every byte of the haystack has been visited, ending
|
||||
/// the iteration.
|
||||
Done
|
||||
Done,
|
||||
}
|
||||
|
||||
/// A searcher for a string pattern.
|
||||
|
@ -189,7 +192,7 @@ pub unsafe trait ReverseSearcher<'a>: Searcher<'a> {
|
|||
|
||||
/// Finds the next `Match` result. See `next_back()`
|
||||
#[inline]
|
||||
fn next_match_back(&mut self) -> Option<(usize, usize)>{
|
||||
fn next_match_back(&mut self) -> Option<(usize, usize)> {
|
||||
loop {
|
||||
match self.next_back() {
|
||||
SearchStep::Match(a, b) => return Some((a, b)),
|
||||
|
@ -201,7 +204,7 @@ pub unsafe trait ReverseSearcher<'a>: Searcher<'a> {
|
|||
|
||||
/// Finds the next `Reject` result. See `next_back()`
|
||||
#[inline]
|
||||
fn next_reject_back(&mut self) -> Option<(usize, usize)>{
|
||||
fn next_reject_back(&mut self) -> Option<(usize, usize)> {
|
||||
loop {
|
||||
match self.next_back() {
|
||||
SearchStep::Reject(a, b) => return Some((a, b)),
|
||||
|
@ -235,7 +238,6 @@ pub unsafe trait ReverseSearcher<'a>: Searcher<'a> {
|
|||
/// `"[aa]a"` or `"a[aa]"`, depending from which side it is searched.
|
||||
pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Impl for char
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -247,7 +249,6 @@ pub struct CharSearcher<'a> {
|
|||
// safety invariant: `finger`/`finger_back` must be a valid utf8 byte index of `haystack`
|
||||
// This invariant can be broken *within* next_match and next_match_back, however
|
||||
// they must exit with fingers on valid code point boundaries.
|
||||
|
||||
/// `finger` is the current byte index of the forward search.
|
||||
/// Imagine that it exists before the byte at its index, i.e.
|
||||
/// `haystack[finger]` is the first byte of the slice we must inspect during
|
||||
|
@ -429,7 +430,7 @@ impl<'a> Pattern<'a> for char {
|
|||
finger_back: haystack.len(),
|
||||
needle: self,
|
||||
utf8_size,
|
||||
utf8_encoded
|
||||
utf8_encoded,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -449,7 +450,9 @@ impl<'a> Pattern<'a> for char {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn is_suffix_of(self, haystack: &'a str) -> bool where Self::Searcher: ReverseSearcher<'a>
|
||||
fn is_suffix_of(self, haystack: &'a str) -> bool
|
||||
where
|
||||
Self::Searcher: ReverseSearcher<'a>,
|
||||
{
|
||||
self.encode_utf8(&mut [0u8; 4]).is_suffix_of(haystack)
|
||||
}
|
||||
|
@ -464,15 +467,20 @@ trait MultiCharEq {
|
|||
fn matches(&mut self, c: char) -> bool;
|
||||
}
|
||||
|
||||
impl<F> MultiCharEq for F where F: FnMut(char) -> bool {
|
||||
impl<F> MultiCharEq for F
|
||||
where
|
||||
F: FnMut(char) -> bool,
|
||||
{
|
||||
#[inline]
|
||||
fn matches(&mut self, c: char) -> bool { (*self)(c) }
|
||||
fn matches(&mut self, c: char) -> bool {
|
||||
(*self)(c)
|
||||
}
|
||||
}
|
||||
|
||||
impl MultiCharEq for &[char] {
|
||||
#[inline]
|
||||
fn matches(&mut self, c: char) -> bool {
|
||||
self.iter().any(|&m| { m == c })
|
||||
self.iter().any(|&m| m == c)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -490,11 +498,7 @@ impl<'a, C: MultiCharEq> Pattern<'a> for MultiCharEqPattern<C> {
|
|||
|
||||
#[inline]
|
||||
fn into_searcher(self, haystack: &'a str) -> MultiCharEqSearcher<'a, C> {
|
||||
MultiCharEqSearcher {
|
||||
haystack,
|
||||
char_eq: self.0,
|
||||
char_indices: haystack.char_indices(),
|
||||
}
|
||||
MultiCharEqSearcher { haystack, char_eq: self.0, char_indices: haystack.char_indices() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -642,10 +646,12 @@ impl<'a, 'b> Pattern<'a> for &'b [char] {
|
|||
/// Associated type for `<F as Pattern<'a>>::Searcher`.
|
||||
#[derive(Clone)]
|
||||
pub struct CharPredicateSearcher<'a, F>(<MultiCharEqPattern<F> as Pattern<'a>>::Searcher)
|
||||
where F: FnMut(char) -> bool;
|
||||
where
|
||||
F: FnMut(char) -> bool;
|
||||
|
||||
impl<F> fmt::Debug for CharPredicateSearcher<'_, F>
|
||||
where F: FnMut(char) -> bool
|
||||
where
|
||||
F: FnMut(char) -> bool,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("CharPredicateSearcher")
|
||||
|
@ -655,22 +661,26 @@ impl<F> fmt::Debug for CharPredicateSearcher<'_, F>
|
|||
}
|
||||
}
|
||||
unsafe impl<'a, F> Searcher<'a> for CharPredicateSearcher<'a, F>
|
||||
where F: FnMut(char) -> bool
|
||||
where
|
||||
F: FnMut(char) -> bool,
|
||||
{
|
||||
searcher_methods!(forward);
|
||||
}
|
||||
|
||||
unsafe impl<'a, F> ReverseSearcher<'a> for CharPredicateSearcher<'a, F>
|
||||
where F: FnMut(char) -> bool
|
||||
where
|
||||
F: FnMut(char) -> bool,
|
||||
{
|
||||
searcher_methods!(reverse);
|
||||
}
|
||||
|
||||
impl<'a, F> DoubleEndedSearcher<'a> for CharPredicateSearcher<'a, F>
|
||||
where F: FnMut(char) -> bool {}
|
||||
impl<'a, F> DoubleEndedSearcher<'a> for CharPredicateSearcher<'a, F> where F: FnMut(char) -> bool {}
|
||||
|
||||
/// Searches for chars that match the given predicate
|
||||
impl<'a, F> Pattern<'a> for F where F: FnMut(char) -> bool {
|
||||
impl<'a, F> Pattern<'a> for F
|
||||
where
|
||||
F: FnMut(char) -> bool,
|
||||
{
|
||||
pattern_methods!(CharPredicateSearcher<'a, F>, MultiCharEqPattern, CharPredicateSearcher);
|
||||
}
|
||||
|
||||
|
@ -712,7 +722,6 @@ impl<'a, 'b> Pattern<'a> for &'b str {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Two Way substring searcher
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -757,9 +766,10 @@ impl<'a, 'b> StrSearcher<'a, 'b> {
|
|||
StrSearcher {
|
||||
haystack,
|
||||
needle,
|
||||
searcher: StrSearcherImpl::TwoWay(
|
||||
TwoWaySearcher::new(needle.as_bytes(), haystack.len())
|
||||
),
|
||||
searcher: StrSearcherImpl::TwoWay(TwoWaySearcher::new(
|
||||
needle.as_bytes(),
|
||||
haystack.len(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -798,10 +808,11 @@ unsafe impl<'a, 'b> Searcher<'a> for StrSearcher<'a, 'b> {
|
|||
return SearchStep::Done;
|
||||
}
|
||||
let is_long = searcher.memory == usize::MAX;
|
||||
match searcher.next::<RejectAndMatch>(self.haystack.as_bytes(),
|
||||
self.needle.as_bytes(),
|
||||
is_long)
|
||||
{
|
||||
match searcher.next::<RejectAndMatch>(
|
||||
self.haystack.as_bytes(),
|
||||
self.needle.as_bytes(),
|
||||
is_long,
|
||||
) {
|
||||
SearchStep::Reject(a, mut b) => {
|
||||
// skip to next char boundary
|
||||
while !self.haystack.is_char_boundary(b) {
|
||||
|
@ -819,27 +830,29 @@ unsafe impl<'a, 'b> Searcher<'a> for StrSearcher<'a, 'b> {
|
|||
#[inline]
|
||||
fn next_match(&mut self) -> Option<(usize, usize)> {
|
||||
match self.searcher {
|
||||
StrSearcherImpl::Empty(..) => {
|
||||
loop {
|
||||
match self.next() {
|
||||
SearchStep::Match(a, b) => return Some((a, b)),
|
||||
SearchStep::Done => return None,
|
||||
SearchStep::Reject(..) => { }
|
||||
}
|
||||
StrSearcherImpl::Empty(..) => loop {
|
||||
match self.next() {
|
||||
SearchStep::Match(a, b) => return Some((a, b)),
|
||||
SearchStep::Done => return None,
|
||||
SearchStep::Reject(..) => {}
|
||||
}
|
||||
}
|
||||
},
|
||||
StrSearcherImpl::TwoWay(ref mut searcher) => {
|
||||
let is_long = searcher.memory == usize::MAX;
|
||||
// write out `true` and `false` cases to encourage the compiler
|
||||
// to specialize the two cases separately.
|
||||
if is_long {
|
||||
searcher.next::<MatchOnly>(self.haystack.as_bytes(),
|
||||
self.needle.as_bytes(),
|
||||
true)
|
||||
searcher.next::<MatchOnly>(
|
||||
self.haystack.as_bytes(),
|
||||
self.needle.as_bytes(),
|
||||
true,
|
||||
)
|
||||
} else {
|
||||
searcher.next::<MatchOnly>(self.haystack.as_bytes(),
|
||||
self.needle.as_bytes(),
|
||||
false)
|
||||
searcher.next::<MatchOnly>(
|
||||
self.haystack.as_bytes(),
|
||||
self.needle.as_bytes(),
|
||||
false,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -868,10 +881,11 @@ unsafe impl<'a, 'b> ReverseSearcher<'a> for StrSearcher<'a, 'b> {
|
|||
return SearchStep::Done;
|
||||
}
|
||||
let is_long = searcher.memory == usize::MAX;
|
||||
match searcher.next_back::<RejectAndMatch>(self.haystack.as_bytes(),
|
||||
self.needle.as_bytes(),
|
||||
is_long)
|
||||
{
|
||||
match searcher.next_back::<RejectAndMatch>(
|
||||
self.haystack.as_bytes(),
|
||||
self.needle.as_bytes(),
|
||||
is_long,
|
||||
) {
|
||||
SearchStep::Reject(mut a, b) => {
|
||||
// skip to next char boundary
|
||||
while !self.haystack.is_char_boundary(a) {
|
||||
|
@ -889,26 +903,28 @@ unsafe impl<'a, 'b> ReverseSearcher<'a> for StrSearcher<'a, 'b> {
|
|||
#[inline]
|
||||
fn next_match_back(&mut self) -> Option<(usize, usize)> {
|
||||
match self.searcher {
|
||||
StrSearcherImpl::Empty(..) => {
|
||||
loop {
|
||||
match self.next_back() {
|
||||
SearchStep::Match(a, b) => return Some((a, b)),
|
||||
SearchStep::Done => return None,
|
||||
SearchStep::Reject(..) => { }
|
||||
}
|
||||
StrSearcherImpl::Empty(..) => loop {
|
||||
match self.next_back() {
|
||||
SearchStep::Match(a, b) => return Some((a, b)),
|
||||
SearchStep::Done => return None,
|
||||
SearchStep::Reject(..) => {}
|
||||
}
|
||||
}
|
||||
},
|
||||
StrSearcherImpl::TwoWay(ref mut searcher) => {
|
||||
let is_long = searcher.memory == usize::MAX;
|
||||
// write out `true` and `false`, like `next_match`
|
||||
if is_long {
|
||||
searcher.next_back::<MatchOnly>(self.haystack.as_bytes(),
|
||||
self.needle.as_bytes(),
|
||||
true)
|
||||
searcher.next_back::<MatchOnly>(
|
||||
self.haystack.as_bytes(),
|
||||
self.needle.as_bytes(),
|
||||
true,
|
||||
)
|
||||
} else {
|
||||
searcher.next_back::<MatchOnly>(self.haystack.as_bytes(),
|
||||
self.needle.as_bytes(),
|
||||
false)
|
||||
searcher.next_back::<MatchOnly>(
|
||||
self.haystack.as_bytes(),
|
||||
self.needle.as_bytes(),
|
||||
false,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1016,12 +1032,11 @@ impl TwoWaySearcher {
|
|||
let (crit_pos_false, period_false) = TwoWaySearcher::maximal_suffix(needle, false);
|
||||
let (crit_pos_true, period_true) = TwoWaySearcher::maximal_suffix(needle, true);
|
||||
|
||||
let (crit_pos, period) =
|
||||
if crit_pos_false > crit_pos_true {
|
||||
(crit_pos_false, period_false)
|
||||
} else {
|
||||
(crit_pos_true, period_true)
|
||||
};
|
||||
let (crit_pos, period) = if crit_pos_false > crit_pos_true {
|
||||
(crit_pos_false, period_false)
|
||||
} else {
|
||||
(crit_pos_true, period_true)
|
||||
};
|
||||
|
||||
// A particularly readable explanation of what's going on here can be found
|
||||
// in Crochemore and Rytter's book "Text Algorithms", ch 13. Specifically
|
||||
|
@ -1032,7 +1047,7 @@ impl TwoWaySearcher {
|
|||
// &v[..period]. If it is, we use "Algorithm CP1". Otherwise we use
|
||||
// "Algorithm CP2", which is optimized for when the period of the needle
|
||||
// is large.
|
||||
if &needle[..crit_pos] == &needle[period.. period + crit_pos] {
|
||||
if &needle[..crit_pos] == &needle[period..period + crit_pos] {
|
||||
// short period case -- the period is exact
|
||||
// compute a separate critical factorization for the reversed needle
|
||||
// x = u' v' where |v'| < period(x).
|
||||
|
@ -1042,9 +1057,11 @@ impl TwoWaySearcher {
|
|||
// (crit_pos = 1, period = 3) while being factored with approximate
|
||||
// period in reverse (crit_pos = 2, period = 2). We use the given
|
||||
// reverse factorization but keep the exact period.
|
||||
let crit_pos_back = needle.len() - cmp::max(
|
||||
TwoWaySearcher::reverse_maximal_suffix(needle, period, false),
|
||||
TwoWaySearcher::reverse_maximal_suffix(needle, period, true));
|
||||
let crit_pos_back = needle.len()
|
||||
- cmp::max(
|
||||
TwoWaySearcher::reverse_maximal_suffix(needle, period, false),
|
||||
TwoWaySearcher::reverse_maximal_suffix(needle, period, true),
|
||||
);
|
||||
|
||||
TwoWaySearcher {
|
||||
crit_pos,
|
||||
|
@ -1095,9 +1112,9 @@ impl TwoWaySearcher {
|
|||
// How far we can jump when we encounter a mismatch is all based on the fact
|
||||
// that (u, v) is a critical factorization for the needle.
|
||||
#[inline]
|
||||
fn next<S>(&mut self, haystack: &[u8], needle: &[u8], long_period: bool)
|
||||
-> S::Output
|
||||
where S: TwoWayStrategy
|
||||
fn next<S>(&mut self, haystack: &[u8], needle: &[u8], long_period: bool) -> S::Output
|
||||
where
|
||||
S: TwoWayStrategy,
|
||||
{
|
||||
// `next()` uses `self.position` as its cursor
|
||||
let old_pos = self.position;
|
||||
|
@ -1128,8 +1145,8 @@ impl TwoWaySearcher {
|
|||
}
|
||||
|
||||
// See if the right part of the needle matches
|
||||
let start = if long_period { self.crit_pos }
|
||||
else { cmp::max(self.crit_pos, self.memory) };
|
||||
let start =
|
||||
if long_period { self.crit_pos } else { cmp::max(self.crit_pos, self.memory) };
|
||||
for i in start..needle.len() {
|
||||
if needle[i] != haystack[self.position + i] {
|
||||
self.position += i - self.crit_pos + 1;
|
||||
|
@ -1178,9 +1195,9 @@ impl TwoWaySearcher {
|
|||
// To search in reverse through the haystack, we search forward through
|
||||
// a reversed haystack with a reversed needle, matching first u' and then v'.
|
||||
#[inline]
|
||||
fn next_back<S>(&mut self, haystack: &[u8], needle: &[u8], long_period: bool)
|
||||
-> S::Output
|
||||
where S: TwoWayStrategy
|
||||
fn next_back<S>(&mut self, haystack: &[u8], needle: &[u8], long_period: bool) -> S::Output
|
||||
where
|
||||
S: TwoWayStrategy,
|
||||
{
|
||||
// `next_back()` uses `self.end` as its cursor -- so that `next()` and `next_back()`
|
||||
// are independent.
|
||||
|
@ -1212,8 +1229,11 @@ impl TwoWaySearcher {
|
|||
}
|
||||
|
||||
// See if the left part of the needle matches
|
||||
let crit = if long_period { self.crit_pos_back }
|
||||
else { cmp::min(self.crit_pos_back, self.memory_back) };
|
||||
let crit = if long_period {
|
||||
self.crit_pos_back
|
||||
} else {
|
||||
cmp::min(self.crit_pos_back, self.memory_back)
|
||||
};
|
||||
for i in (0..crit).rev() {
|
||||
if needle[i] != haystack[self.end - needle.len() + i] {
|
||||
self.end -= self.crit_pos_back - i;
|
||||
|
@ -1225,8 +1245,7 @@ impl TwoWaySearcher {
|
|||
}
|
||||
|
||||
// See if the right part of the needle matches
|
||||
let needle_end = if long_period { needle.len() }
|
||||
else { self.memory_back };
|
||||
let needle_end = if long_period { needle.len() } else { self.memory_back };
|
||||
for i in self.crit_pos_back..needle_end {
|
||||
if needle[i] != haystack[self.end - needle.len() + i] {
|
||||
self.end -= self.period;
|
||||
|
@ -1266,7 +1285,7 @@ impl TwoWaySearcher {
|
|||
let mut left = 0; // Corresponds to i in the paper
|
||||
let mut right = 1; // Corresponds to j in the paper
|
||||
let mut offset = 0; // Corresponds to k in the paper, but starting at 0
|
||||
// to match 0-based indexing.
|
||||
// to match 0-based indexing.
|
||||
let mut period = 1; // Corresponds to p in the paper
|
||||
|
||||
while let Some(&a) = arr.get(right + offset) {
|
||||
|
@ -1308,13 +1327,11 @@ impl TwoWaySearcher {
|
|||
// a critical factorization.
|
||||
//
|
||||
// For long period cases, the resulting period is not exact (it is too short).
|
||||
fn reverse_maximal_suffix(arr: &[u8], known_period: usize,
|
||||
order_greater: bool) -> usize
|
||||
{
|
||||
fn reverse_maximal_suffix(arr: &[u8], known_period: usize, order_greater: bool) -> usize {
|
||||
let mut left = 0; // Corresponds to i in the paper
|
||||
let mut right = 1; // Corresponds to j in the paper
|
||||
let mut offset = 0; // Corresponds to k in the paper, but starting at 0
|
||||
// to match 0-based indexing.
|
||||
// to match 0-based indexing.
|
||||
let mut period = 1; // Corresponds to p in the paper
|
||||
let n = arr.len();
|
||||
|
||||
|
@ -1360,29 +1377,41 @@ trait TwoWayStrategy {
|
|||
}
|
||||
|
||||
/// Skip to match intervals as quickly as possible
|
||||
enum MatchOnly { }
|
||||
enum MatchOnly {}
|
||||
|
||||
impl TwoWayStrategy for MatchOnly {
|
||||
type Output = Option<(usize, usize)>;
|
||||
|
||||
#[inline]
|
||||
fn use_early_reject() -> bool { false }
|
||||
fn use_early_reject() -> bool {
|
||||
false
|
||||
}
|
||||
#[inline]
|
||||
fn rejecting(_a: usize, _b: usize) -> Self::Output { None }
|
||||
fn rejecting(_a: usize, _b: usize) -> Self::Output {
|
||||
None
|
||||
}
|
||||
#[inline]
|
||||
fn matching(a: usize, b: usize) -> Self::Output { Some((a, b)) }
|
||||
fn matching(a: usize, b: usize) -> Self::Output {
|
||||
Some((a, b))
|
||||
}
|
||||
}
|
||||
|
||||
/// Emit Rejects regularly
|
||||
enum RejectAndMatch { }
|
||||
enum RejectAndMatch {}
|
||||
|
||||
impl TwoWayStrategy for RejectAndMatch {
|
||||
type Output = SearchStep;
|
||||
|
||||
#[inline]
|
||||
fn use_early_reject() -> bool { true }
|
||||
fn use_early_reject() -> bool {
|
||||
true
|
||||
}
|
||||
#[inline]
|
||||
fn rejecting(a: usize, b: usize) -> Self::Output { SearchStep::Reject(a, b) }
|
||||
fn rejecting(a: usize, b: usize) -> Self::Output {
|
||||
SearchStep::Reject(a, b)
|
||||
}
|
||||
#[inline]
|
||||
fn matching(a: usize, b: usize) -> Self::Output { SearchStep::Match(a, b) }
|
||||
fn matching(a: usize, b: usize) -> Self::Output {
|
||||
SearchStep::Match(a, b)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,9 +120,9 @@
|
|||
|
||||
use self::Ordering::*;
|
||||
|
||||
use crate::intrinsics;
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::fmt;
|
||||
use crate::intrinsics;
|
||||
|
||||
use crate::hint::spin_loop;
|
||||
|
||||
|
@ -313,7 +313,7 @@ pub enum Ordering {
|
|||
#[rustc_deprecated(
|
||||
since = "1.34.0",
|
||||
reason = "the `new` function is now preferred",
|
||||
suggestion = "AtomicBool::new(false)",
|
||||
suggestion = "AtomicBool::new(false)"
|
||||
)]
|
||||
pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
|
@ -557,12 +557,13 @@ impl AtomicBool {
|
|||
#[inline]
|
||||
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
pub fn compare_exchange(&self,
|
||||
current: bool,
|
||||
new: bool,
|
||||
success: Ordering,
|
||||
failure: Ordering)
|
||||
-> Result<bool, bool> {
|
||||
pub fn compare_exchange(
|
||||
&self,
|
||||
current: bool,
|
||||
new: bool,
|
||||
success: Ordering,
|
||||
failure: Ordering,
|
||||
) -> Result<bool, bool> {
|
||||
match unsafe {
|
||||
atomic_compare_exchange(self.v.get(), current as u8, new as u8, success, failure)
|
||||
} {
|
||||
|
@ -613,12 +614,13 @@ impl AtomicBool {
|
|||
#[inline]
|
||||
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
pub fn compare_exchange_weak(&self,
|
||||
current: bool,
|
||||
new: bool,
|
||||
success: Ordering,
|
||||
failure: Ordering)
|
||||
-> Result<bool, bool> {
|
||||
pub fn compare_exchange_weak(
|
||||
&self,
|
||||
current: bool,
|
||||
new: bool,
|
||||
success: Ordering,
|
||||
failure: Ordering,
|
||||
) -> Result<bool, bool> {
|
||||
match unsafe {
|
||||
atomic_compare_exchange_weak(self.v.get(), current as u8, new as u8, success, failure)
|
||||
} {
|
||||
|
@ -834,9 +836,7 @@ impl AtomicBool {
|
|||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "atomic_mut_ptr",
|
||||
reason = "recently added",
|
||||
issue = "66893")]
|
||||
#[unstable(feature = "atomic_mut_ptr", reason = "recently added", issue = "66893")]
|
||||
pub fn as_mut_ptr(&self) -> *mut bool {
|
||||
self.v.get() as *mut bool
|
||||
}
|
||||
|
@ -1073,18 +1073,21 @@ impl<T> AtomicPtr<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
pub fn compare_exchange(&self,
|
||||
current: *mut T,
|
||||
new: *mut T,
|
||||
success: Ordering,
|
||||
failure: Ordering)
|
||||
-> Result<*mut T, *mut T> {
|
||||
pub fn compare_exchange(
|
||||
&self,
|
||||
current: *mut T,
|
||||
new: *mut T,
|
||||
success: Ordering,
|
||||
failure: Ordering,
|
||||
) -> Result<*mut T, *mut T> {
|
||||
unsafe {
|
||||
let res = atomic_compare_exchange(self.p.get() as *mut usize,
|
||||
current as usize,
|
||||
new as usize,
|
||||
success,
|
||||
failure);
|
||||
let res = atomic_compare_exchange(
|
||||
self.p.get() as *mut usize,
|
||||
current as usize,
|
||||
new as usize,
|
||||
success,
|
||||
failure,
|
||||
);
|
||||
match res {
|
||||
Ok(x) => Ok(x as *mut T),
|
||||
Err(x) => Err(x as *mut T),
|
||||
|
@ -1133,18 +1136,21 @@ impl<T> AtomicPtr<T> {
|
|||
#[inline]
|
||||
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
pub fn compare_exchange_weak(&self,
|
||||
current: *mut T,
|
||||
new: *mut T,
|
||||
success: Ordering,
|
||||
failure: Ordering)
|
||||
-> Result<*mut T, *mut T> {
|
||||
pub fn compare_exchange_weak(
|
||||
&self,
|
||||
current: *mut T,
|
||||
new: *mut T,
|
||||
success: Ordering,
|
||||
failure: Ordering,
|
||||
) -> Result<*mut T, *mut T> {
|
||||
unsafe {
|
||||
let res = atomic_compare_exchange_weak(self.p.get() as *mut usize,
|
||||
current as usize,
|
||||
new as usize,
|
||||
success,
|
||||
failure);
|
||||
let res = atomic_compare_exchange_weak(
|
||||
self.p.get() as *mut usize,
|
||||
current as usize,
|
||||
new as usize,
|
||||
success,
|
||||
failure,
|
||||
);
|
||||
match res {
|
||||
Ok(x) => Ok(x as *mut T),
|
||||
Err(x) => Err(x as *mut T),
|
||||
|
@ -1166,14 +1172,18 @@ impl From<bool> for AtomicBool {
|
|||
/// assert_eq!(format!("{:?}", atomic_bool), "true")
|
||||
/// ```
|
||||
#[inline]
|
||||
fn from(b: bool) -> Self { Self::new(b) }
|
||||
fn from(b: bool) -> Self {
|
||||
Self::new(b)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_has_atomic_load_store = "ptr")]
|
||||
#[stable(feature = "atomic_from", since = "1.23.0")]
|
||||
impl<T> From<*mut T> for AtomicPtr<T> {
|
||||
#[inline]
|
||||
fn from(p: *mut T) -> Self { Self::new(p) }
|
||||
fn from(p: *mut T) -> Self {
|
||||
Self::new(p)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_has_atomic_load_store = "8")]
|
||||
|
@ -2156,20 +2166,26 @@ atomic_int! {
|
|||
#[cfg(target_has_atomic_load_store = "ptr")]
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
macro_rules! ptr_width {
|
||||
() => { 2 }
|
||||
() => {
|
||||
2
|
||||
};
|
||||
}
|
||||
#[cfg(target_has_atomic_load_store = "ptr")]
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
macro_rules! ptr_width {
|
||||
() => { 4 }
|
||||
() => {
|
||||
4
|
||||
};
|
||||
}
|
||||
#[cfg(target_has_atomic_load_store = "ptr")]
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
macro_rules! ptr_width {
|
||||
() => { 8 }
|
||||
() => {
|
||||
8
|
||||
};
|
||||
}
|
||||
#[cfg(target_has_atomic_load_store = "ptr")]
|
||||
atomic_int!{
|
||||
atomic_int! {
|
||||
cfg(target_has_atomic = "ptr"),
|
||||
stable(feature = "rust1", since = "1.0.0"),
|
||||
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
|
||||
|
@ -2187,7 +2203,7 @@ atomic_int!{
|
|||
isize AtomicIsize ATOMIC_ISIZE_INIT
|
||||
}
|
||||
#[cfg(target_has_atomic_load_store = "ptr")]
|
||||
atomic_int!{
|
||||
atomic_int! {
|
||||
cfg(target_has_atomic = "ptr"),
|
||||
stable(feature = "rust1", since = "1.0.0"),
|
||||
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
|
||||
|
@ -2279,12 +2295,13 @@ unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|||
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
unsafe fn atomic_compare_exchange<T>(dst: *mut T,
|
||||
old: T,
|
||||
new: T,
|
||||
success: Ordering,
|
||||
failure: Ordering)
|
||||
-> Result<T, T> {
|
||||
unsafe fn atomic_compare_exchange<T>(
|
||||
dst: *mut T,
|
||||
old: T,
|
||||
new: T,
|
||||
success: Ordering,
|
||||
failure: Ordering,
|
||||
) -> Result<T, T> {
|
||||
let (val, ok) = match (success, failure) {
|
||||
(Acquire, Acquire) => intrinsics::atomic_cxchg_acq(dst, old, new),
|
||||
(Release, Relaxed) => intrinsics::atomic_cxchg_rel(dst, old, new),
|
||||
|
@ -2304,12 +2321,13 @@ unsafe fn atomic_compare_exchange<T>(dst: *mut T,
|
|||
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T,
|
||||
old: T,
|
||||
new: T,
|
||||
success: Ordering,
|
||||
failure: Ordering)
|
||||
-> Result<T, T> {
|
||||
unsafe fn atomic_compare_exchange_weak<T>(
|
||||
dst: *mut T,
|
||||
old: T,
|
||||
new: T,
|
||||
success: Ordering,
|
||||
failure: Ordering,
|
||||
) -> Result<T, T> {
|
||||
let (val, ok) = match (success, failure) {
|
||||
(Acquire, Acquire) => intrinsics::atomic_cxchgweak_acq(dst, old, new),
|
||||
(Release, Relaxed) => intrinsics::atomic_cxchgweak_rel(dst, old, new),
|
||||
|
@ -2525,7 +2543,6 @@ pub fn fence(order: Ordering) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// A compiler memory fence.
|
||||
///
|
||||
/// `compiler_fence` does not emit any machine code, but restricts the kinds
|
||||
|
@ -2613,7 +2630,6 @@ pub fn compiler_fence(order: Ordering) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(target_has_atomic_load_store = "8")]
|
||||
#[stable(feature = "atomic_debug", since = "1.3.0")]
|
||||
impl fmt::Debug for AtomicBool {
|
||||
|
|
|
@ -101,7 +101,7 @@ fn test_ordering_then_with() {
|
|||
fn test_user_defined_eq() {
|
||||
// Our type.
|
||||
struct SketchyNum {
|
||||
num : isize
|
||||
num: isize,
|
||||
}
|
||||
|
||||
// Our implementation of `PartialEq` to support `==` and `!=`.
|
||||
|
@ -113,6 +113,6 @@ fn test_user_defined_eq() {
|
|||
}
|
||||
|
||||
// Now these binary operators will work when applied!
|
||||
assert!(SketchyNum {num: 37} == SketchyNum {num: 34});
|
||||
assert!(SketchyNum {num: 25} != SketchyNum {num: 57});
|
||||
assert!(SketchyNum { num: 37 } == SketchyNum { num: 34 });
|
||||
assert!(SketchyNum { num: 25 } != SketchyNum { num: 57 });
|
||||
}
|
||||
|
|
|
@ -21,18 +21,17 @@ mod debug_struct {
|
|||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("Foo")
|
||||
.field("bar", &true)
|
||||
.finish()
|
||||
fmt.debug_struct("Foo").field("bar", &true).finish()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("Foo { bar: true }", format!("{:?}", Foo));
|
||||
assert_eq!(
|
||||
"Foo {
|
||||
"Foo {
|
||||
bar: true,
|
||||
}",
|
||||
format!("{:#?}", Foo));
|
||||
format!("{:#?}", Foo)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -50,11 +49,12 @@ mod debug_struct {
|
|||
|
||||
assert_eq!("Foo { bar: true, baz: 10/20 }", format!("{:?}", Foo));
|
||||
assert_eq!(
|
||||
"Foo {
|
||||
"Foo {
|
||||
bar: true,
|
||||
baz: 10/20,
|
||||
}",
|
||||
format!("{:#?}", Foo));
|
||||
format!("{:#?}", Foo)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -74,24 +74,24 @@ mod debug_struct {
|
|||
|
||||
impl fmt::Debug for Bar {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("Bar")
|
||||
.field("foo", &Foo)
|
||||
.field("hello", &"world")
|
||||
.finish()
|
||||
fmt.debug_struct("Bar").field("foo", &Foo).field("hello", &"world").finish()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("Bar { foo: Foo { bar: true, baz: 10/20 }, hello: \"world\" }",
|
||||
format!("{:?}", Bar));
|
||||
assert_eq!(
|
||||
"Bar {
|
||||
"Bar { foo: Foo { bar: true, baz: 10/20 }, hello: \"world\" }",
|
||||
format!("{:?}", Bar)
|
||||
);
|
||||
assert_eq!(
|
||||
"Bar {
|
||||
foo: Foo {
|
||||
bar: true,
|
||||
baz: 10/20,
|
||||
},
|
||||
hello: \"world\",
|
||||
}",
|
||||
format!("{:#?}", Bar));
|
||||
format!("{:#?}", Bar)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,18 +118,17 @@ mod debug_tuple {
|
|||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_tuple("Foo")
|
||||
.field(&true)
|
||||
.finish()
|
||||
fmt.debug_tuple("Foo").field(&true).finish()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("Foo(true)", format!("{:?}", Foo));
|
||||
assert_eq!(
|
||||
"Foo(
|
||||
"Foo(
|
||||
true,
|
||||
)",
|
||||
format!("{:#?}", Foo));
|
||||
format!("{:#?}", Foo)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -138,20 +137,18 @@ mod debug_tuple {
|
|||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_tuple("Foo")
|
||||
.field(&true)
|
||||
.field(&format_args!("{}/{}", 10, 20))
|
||||
.finish()
|
||||
fmt.debug_tuple("Foo").field(&true).field(&format_args!("{}/{}", 10, 20)).finish()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("Foo(true, 10/20)", format!("{:?}", Foo));
|
||||
assert_eq!(
|
||||
"Foo(
|
||||
"Foo(
|
||||
true,
|
||||
10/20,
|
||||
)",
|
||||
format!("{:#?}", Foo));
|
||||
format!("{:#?}", Foo)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -160,10 +157,7 @@ mod debug_tuple {
|
|||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_tuple("Foo")
|
||||
.field(&true)
|
||||
.field(&format_args!("{}/{}", 10, 20))
|
||||
.finish()
|
||||
fmt.debug_tuple("Foo").field(&true).field(&format_args!("{}/{}", 10, 20)).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,24 +165,21 @@ mod debug_tuple {
|
|||
|
||||
impl fmt::Debug for Bar {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_tuple("Bar")
|
||||
.field(&Foo)
|
||||
.field(&"world")
|
||||
.finish()
|
||||
fmt.debug_tuple("Bar").field(&Foo).field(&"world").finish()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("Bar(Foo(true, 10/20), \"world\")",
|
||||
format!("{:?}", Bar));
|
||||
assert_eq!("Bar(Foo(true, 10/20), \"world\")", format!("{:?}", Bar));
|
||||
assert_eq!(
|
||||
"Bar(
|
||||
"Bar(
|
||||
Foo(
|
||||
true,
|
||||
10/20,
|
||||
),
|
||||
\"world\",
|
||||
)",
|
||||
format!("{:#?}", Bar));
|
||||
format!("{:#?}", Bar)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,9 +206,7 @@ mod debug_map {
|
|||
|
||||
impl fmt::Debug for Entry {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_map()
|
||||
.entry(&"bar", &true)
|
||||
.finish()
|
||||
fmt.debug_map().entry(&"bar", &true).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,9 +214,7 @@ mod debug_map {
|
|||
|
||||
impl fmt::Debug for KeyValue {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_map()
|
||||
.key(&"bar").value(&true)
|
||||
.finish()
|
||||
fmt.debug_map().key(&"bar").value(&true).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,10 +223,11 @@ mod debug_map {
|
|||
|
||||
assert_eq!("{\"bar\": true}", format!("{:?}", Entry));
|
||||
assert_eq!(
|
||||
"{
|
||||
"{
|
||||
\"bar\": true,
|
||||
}",
|
||||
format!("{:#?}", Entry));
|
||||
format!("{:#?}", Entry)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -260,8 +248,10 @@ mod debug_map {
|
|||
impl fmt::Debug for KeyValue {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_map()
|
||||
.key(&"bar").value(&true)
|
||||
.key(&10).value(&format_args!("{}/{}", 10, 20))
|
||||
.key(&"bar")
|
||||
.value(&true)
|
||||
.key(&10)
|
||||
.value(&format_args!("{}/{}", 10, 20))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
@ -271,11 +261,12 @@ mod debug_map {
|
|||
|
||||
assert_eq!("{\"bar\": true, 10: 10/20}", format!("{:?}", Entry));
|
||||
assert_eq!(
|
||||
"{
|
||||
"{
|
||||
\"bar\": true,
|
||||
10: 10/20,
|
||||
}",
|
||||
format!("{:#?}", Entry));
|
||||
format!("{:#?}", Entry)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -295,18 +286,17 @@ mod debug_map {
|
|||
|
||||
impl fmt::Debug for Bar {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_map()
|
||||
.entry(&"foo", &Foo)
|
||||
.entry(&Foo, &"world")
|
||||
.finish()
|
||||
fmt.debug_map().entry(&"foo", &Foo).entry(&Foo, &"world").finish()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("{\"foo\": {\"bar\": true, 10: 10/20}, \
|
||||
{\"bar\": true, 10: 10/20}: \"world\"}",
|
||||
format!("{:?}", Bar));
|
||||
assert_eq!(
|
||||
"{
|
||||
"{\"foo\": {\"bar\": true, 10: 10/20}, \
|
||||
{\"bar\": true, 10: 10/20}: \"world\"}",
|
||||
format!("{:?}", Bar)
|
||||
);
|
||||
assert_eq!(
|
||||
"{
|
||||
\"foo\": {
|
||||
\"bar\": true,
|
||||
10: 10/20,
|
||||
|
@ -316,7 +306,8 @@ mod debug_map {
|
|||
10: 10/20,
|
||||
}: \"world\",
|
||||
}",
|
||||
format!("{:#?}", Bar));
|
||||
format!("{:#?}", Bar)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -366,10 +357,7 @@ mod debug_map {
|
|||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_map()
|
||||
.key(&"bar")
|
||||
.key(&"invalid")
|
||||
.finish()
|
||||
fmt.debug_map().key(&"bar").key(&"invalid").finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -383,9 +371,7 @@ mod debug_map {
|
|||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_map()
|
||||
.key(&"bar")
|
||||
.finish()
|
||||
fmt.debug_map().key(&"bar").finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -399,10 +385,7 @@ mod debug_map {
|
|||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_map()
|
||||
.value(&"invalid")
|
||||
.key(&"bar")
|
||||
.finish()
|
||||
fmt.debug_map().value(&"invalid").key(&"bar").finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -433,18 +416,17 @@ mod debug_set {
|
|||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_set()
|
||||
.entry(&true)
|
||||
.finish()
|
||||
fmt.debug_set().entry(&true).finish()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("{true}", format!("{:?}", Foo));
|
||||
assert_eq!(
|
||||
"{
|
||||
"{
|
||||
true,
|
||||
}",
|
||||
format!("{:#?}", Foo));
|
||||
format!("{:#?}", Foo)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -453,20 +435,18 @@ mod debug_set {
|
|||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_set()
|
||||
.entry(&true)
|
||||
.entry(&format_args!("{}/{}", 10, 20))
|
||||
.finish()
|
||||
fmt.debug_set().entry(&true).entry(&format_args!("{}/{}", 10, 20)).finish()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("{true, 10/20}", format!("{:?}", Foo));
|
||||
assert_eq!(
|
||||
"{
|
||||
"{
|
||||
true,
|
||||
10/20,
|
||||
}",
|
||||
format!("{:#?}", Foo));
|
||||
format!("{:#?}", Foo)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -475,10 +455,7 @@ mod debug_set {
|
|||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_set()
|
||||
.entry(&true)
|
||||
.entry(&format_args!("{}/{}", 10, 20))
|
||||
.finish()
|
||||
fmt.debug_set().entry(&true).entry(&format_args!("{}/{}", 10, 20)).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -486,24 +463,21 @@ mod debug_set {
|
|||
|
||||
impl fmt::Debug for Bar {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_set()
|
||||
.entry(&Foo)
|
||||
.entry(&"world")
|
||||
.finish()
|
||||
fmt.debug_set().entry(&Foo).entry(&"world").finish()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("{{true, 10/20}, \"world\"}",
|
||||
format!("{:?}", Bar));
|
||||
assert_eq!("{{true, 10/20}, \"world\"}", format!("{:?}", Bar));
|
||||
assert_eq!(
|
||||
"{
|
||||
"{
|
||||
{
|
||||
true,
|
||||
10/20,
|
||||
},
|
||||
\"world\",
|
||||
}",
|
||||
format!("{:#?}", Bar));
|
||||
format!("{:#?}", Bar)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -530,18 +504,17 @@ mod debug_list {
|
|||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_list()
|
||||
.entry(&true)
|
||||
.finish()
|
||||
fmt.debug_list().entry(&true).finish()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("[true]", format!("{:?}", Foo));
|
||||
assert_eq!(
|
||||
"[
|
||||
"[
|
||||
true,
|
||||
]",
|
||||
format!("{:#?}", Foo));
|
||||
format!("{:#?}", Foo)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -550,20 +523,18 @@ mod debug_list {
|
|||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_list()
|
||||
.entry(&true)
|
||||
.entry(&format_args!("{}/{}", 10, 20))
|
||||
.finish()
|
||||
fmt.debug_list().entry(&true).entry(&format_args!("{}/{}", 10, 20)).finish()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("[true, 10/20]", format!("{:?}", Foo));
|
||||
assert_eq!(
|
||||
"[
|
||||
"[
|
||||
true,
|
||||
10/20,
|
||||
]",
|
||||
format!("{:#?}", Foo));
|
||||
format!("{:#?}", Foo)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -572,10 +543,7 @@ mod debug_list {
|
|||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_list()
|
||||
.entry(&true)
|
||||
.entry(&format_args!("{}/{}", 10, 20))
|
||||
.finish()
|
||||
fmt.debug_list().entry(&true).entry(&format_args!("{}/{}", 10, 20)).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -583,24 +551,21 @@ mod debug_list {
|
|||
|
||||
impl fmt::Debug for Bar {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_list()
|
||||
.entry(&Foo)
|
||||
.entry(&"world")
|
||||
.finish()
|
||||
fmt.debug_list().entry(&Foo).entry(&"world").finish()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("[[true, 10/20], \"world\"]",
|
||||
format!("{:?}", Bar));
|
||||
assert_eq!("[[true, 10/20], \"world\"]", format!("{:?}", Bar));
|
||||
assert_eq!(
|
||||
"[
|
||||
"[
|
||||
[
|
||||
true,
|
||||
10/20,
|
||||
],
|
||||
\"world\",
|
||||
]",
|
||||
format!("{:#?}", Bar));
|
||||
format!("{:#?}", Bar)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -627,34 +592,54 @@ fn test_formatting_parameters_are_forwarded() {
|
|||
assert_eq!(format!("{:03?}", list), "[1024, 007]");
|
||||
assert_eq!(format!("{:03?}", map), r#"{"bar": 1024, "baz": 007}"#);
|
||||
assert_eq!(format!("{:03?}", set), "{007, 1024}");
|
||||
assert_eq!(format!("{:#03?}", struct_), "
|
||||
assert_eq!(
|
||||
format!("{:#03?}", struct_),
|
||||
"
|
||||
Foo {
|
||||
bar: 1024,
|
||||
baz: 007,
|
||||
}
|
||||
".trim());
|
||||
assert_eq!(format!("{:#03?}", tuple), "
|
||||
"
|
||||
.trim()
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:#03?}", tuple),
|
||||
"
|
||||
(
|
||||
1024,
|
||||
007,
|
||||
)
|
||||
".trim());
|
||||
assert_eq!(format!("{:#03?}", list), "
|
||||
"
|
||||
.trim()
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:#03?}", list),
|
||||
"
|
||||
[
|
||||
1024,
|
||||
007,
|
||||
]
|
||||
".trim());
|
||||
assert_eq!(format!("{:#03?}", map), r#"
|
||||
"
|
||||
.trim()
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:#03?}", map),
|
||||
r#"
|
||||
{
|
||||
"bar": 1024,
|
||||
"baz": 007,
|
||||
}
|
||||
"#.trim());
|
||||
assert_eq!(format!("{:#03?}", set), "
|
||||
"#
|
||||
.trim()
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:#03?}", set),
|
||||
"
|
||||
{
|
||||
007,
|
||||
1024,
|
||||
}
|
||||
".trim());
|
||||
"
|
||||
.trim()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,8 @@ fn test_writer_hasher() {
|
|||
let ptr = 5_usize as *mut i32;
|
||||
assert_eq!(hash(&ptr), 5);
|
||||
|
||||
if cfg!(miri) { // Miri cannot hash pointers
|
||||
if cfg!(miri) {
|
||||
// Miri cannot hash pointers
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,58 +1,58 @@
|
|||
use core::cell::Cell;
|
||||
use core::convert::TryFrom;
|
||||
use core::iter::*;
|
||||
use core::{i8, i16, isize};
|
||||
use core::usize;
|
||||
use core::{i16, i8, isize};
|
||||
|
||||
#[test]
|
||||
fn test_lt() {
|
||||
let empty: [isize; 0] = [];
|
||||
let xs = [1,2,3];
|
||||
let ys = [1,2,0];
|
||||
let xs = [1, 2, 3];
|
||||
let ys = [1, 2, 0];
|
||||
|
||||
assert!(!xs.iter().lt(ys.iter()));
|
||||
assert!(!xs.iter().le(ys.iter()));
|
||||
assert!( xs.iter().gt(ys.iter()));
|
||||
assert!( xs.iter().ge(ys.iter()));
|
||||
assert!(xs.iter().gt(ys.iter()));
|
||||
assert!(xs.iter().ge(ys.iter()));
|
||||
|
||||
assert!( ys.iter().lt(xs.iter()));
|
||||
assert!( ys.iter().le(xs.iter()));
|
||||
assert!(ys.iter().lt(xs.iter()));
|
||||
assert!(ys.iter().le(xs.iter()));
|
||||
assert!(!ys.iter().gt(xs.iter()));
|
||||
assert!(!ys.iter().ge(xs.iter()));
|
||||
|
||||
assert!( empty.iter().lt(xs.iter()));
|
||||
assert!( empty.iter().le(xs.iter()));
|
||||
assert!(empty.iter().lt(xs.iter()));
|
||||
assert!(empty.iter().le(xs.iter()));
|
||||
assert!(!empty.iter().gt(xs.iter()));
|
||||
assert!(!empty.iter().ge(xs.iter()));
|
||||
|
||||
// Sequence with NaN
|
||||
let u = [1.0f64, 2.0];
|
||||
let v = [0.0f64/0.0, 3.0];
|
||||
let v = [0.0f64 / 0.0, 3.0];
|
||||
|
||||
assert!(!u.iter().lt(v.iter()));
|
||||
assert!(!u.iter().le(v.iter()));
|
||||
assert!(!u.iter().gt(v.iter()));
|
||||
assert!(!u.iter().ge(v.iter()));
|
||||
|
||||
let a = [0.0f64/0.0];
|
||||
let a = [0.0f64 / 0.0];
|
||||
let b = [1.0f64];
|
||||
let c = [2.0f64];
|
||||
|
||||
assert!(a.iter().lt(b.iter()) == (a[0] < b[0]));
|
||||
assert!(a.iter().lt(b.iter()) == (a[0] < b[0]));
|
||||
assert!(a.iter().le(b.iter()) == (a[0] <= b[0]));
|
||||
assert!(a.iter().gt(b.iter()) == (a[0] > b[0]));
|
||||
assert!(a.iter().gt(b.iter()) == (a[0] > b[0]));
|
||||
assert!(a.iter().ge(b.iter()) == (a[0] >= b[0]));
|
||||
|
||||
assert!(c.iter().lt(b.iter()) == (c[0] < b[0]));
|
||||
assert!(c.iter().lt(b.iter()) == (c[0] < b[0]));
|
||||
assert!(c.iter().le(b.iter()) == (c[0] <= b[0]));
|
||||
assert!(c.iter().gt(b.iter()) == (c[0] > b[0]));
|
||||
assert!(c.iter().gt(b.iter()) == (c[0] > b[0]));
|
||||
assert!(c.iter().ge(b.iter()) == (c[0] >= b[0]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multi_iter() {
|
||||
let xs = [1,2,3,4];
|
||||
let ys = [4,3,2,1];
|
||||
let xs = [1, 2, 3, 4];
|
||||
let ys = [4, 3, 2, 1];
|
||||
assert!(xs.iter().eq(ys.iter().rev()));
|
||||
assert!(xs.iter().lt(xs.iter().skip(2)));
|
||||
}
|
||||
|
@ -229,11 +229,7 @@ fn test_iterator_chain_size_hint() {
|
|||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
if self.is_empty {
|
||||
(0, Some(0))
|
||||
} else {
|
||||
(1, Some(1))
|
||||
}
|
||||
if self.is_empty { (0, Some(0)) } else { (1, Some(1)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,7 +273,9 @@ fn test_zip_nth() {
|
|||
fn test_zip_nth_side_effects() {
|
||||
let mut a = Vec::new();
|
||||
let mut b = Vec::new();
|
||||
let value = [1, 2, 3, 4, 5, 6].iter().cloned()
|
||||
let value = [1, 2, 3, 4, 5, 6]
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|n| {
|
||||
a.push(n);
|
||||
n * 10
|
||||
|
@ -356,7 +354,9 @@ fn test_iterator_step_by_nth_overflow() {
|
|||
struct Test(Bigger);
|
||||
impl Iterator for &mut Test {
|
||||
type Item = i32;
|
||||
fn next(&mut self) -> Option<Self::Item> { Some(21) }
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
Some(21)
|
||||
}
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||
self.0 += n as Bigger + 1;
|
||||
Some(42)
|
||||
|
@ -499,7 +499,7 @@ fn test_iterator_step_by_size_hint() {
|
|||
let mut it = StubSizeHint(usize::MAX, None).step_by(1);
|
||||
assert_eq!(it.size_hint(), (usize::MAX, None));
|
||||
it.next();
|
||||
assert_eq!(it.size_hint(), (usize::MAX-1, None));
|
||||
assert_eq!(it.size_hint(), (usize::MAX - 1, None));
|
||||
|
||||
// still infinite with larger step
|
||||
let mut it = StubSizeHint(7, None).step_by(3);
|
||||
|
@ -508,18 +508,24 @@ fn test_iterator_step_by_size_hint() {
|
|||
assert_eq!(it.size_hint(), (2, None));
|
||||
|
||||
// propagates ExactSizeIterator
|
||||
let a = [1,2,3,4,5];
|
||||
let a = [1, 2, 3, 4, 5];
|
||||
let it = a.iter().step_by(2);
|
||||
assert_eq!(it.len(), 3);
|
||||
|
||||
// Cannot be TrustedLen as a step greater than one makes an iterator
|
||||
// with (usize::MAX, None) no longer meet the safety requirements
|
||||
trait TrustedLenCheck { fn test(self) -> bool; }
|
||||
impl<T:Iterator> TrustedLenCheck for T {
|
||||
default fn test(self) -> bool { false }
|
||||
trait TrustedLenCheck {
|
||||
fn test(self) -> bool;
|
||||
}
|
||||
impl<T:TrustedLen> TrustedLenCheck for T {
|
||||
fn test(self) -> bool { true }
|
||||
impl<T: Iterator> TrustedLenCheck for T {
|
||||
default fn test(self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
impl<T: TrustedLen> TrustedLenCheck for T {
|
||||
fn test(self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
assert!(TrustedLenCheck::test(a.iter()));
|
||||
assert!(!TrustedLenCheck::test(a.iter().step_by(1)));
|
||||
|
@ -527,23 +533,22 @@ fn test_iterator_step_by_size_hint() {
|
|||
|
||||
#[test]
|
||||
fn test_filter_map() {
|
||||
let it = (0..).step_by(1).take(10)
|
||||
.filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
|
||||
assert_eq!(it.collect::<Vec<usize>>(), [0*0, 2*2, 4*4, 6*6, 8*8]);
|
||||
let it = (0..).step_by(1).take(10).filter_map(|x| if x % 2 == 0 { Some(x * x) } else { None });
|
||||
assert_eq!(it.collect::<Vec<usize>>(), [0 * 0, 2 * 2, 4 * 4, 6 * 6, 8 * 8]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filter_map_fold() {
|
||||
let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8];
|
||||
let ys = [0*0, 2*2, 4*4, 6*6, 8*8];
|
||||
let it = xs.iter().filter_map(|&x| if x % 2 == 0 { Some(x*x) } else { None });
|
||||
let ys = [0 * 0, 2 * 2, 4 * 4, 6 * 6, 8 * 8];
|
||||
let it = xs.iter().filter_map(|&x| if x % 2 == 0 { Some(x * x) } else { None });
|
||||
let i = it.fold(0, |i, x| {
|
||||
assert_eq!(x, ys[i]);
|
||||
i + 1
|
||||
});
|
||||
assert_eq!(i, ys.len());
|
||||
|
||||
let it = xs.iter().filter_map(|&x| if x % 2 == 0 { Some(x*x) } else { None });
|
||||
let it = xs.iter().filter_map(|&x| if x % 2 == 0 { Some(x * x) } else { None });
|
||||
let i = it.rfold(ys.len(), |i, x| {
|
||||
assert_eq!(x, ys[i - 1]);
|
||||
i - 1
|
||||
|
@ -736,7 +741,6 @@ fn test_iterator_peekable_count() {
|
|||
|
||||
let mut it = zs.iter().peekable();
|
||||
assert_eq!(it.peek(), None);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -805,10 +809,7 @@ pub struct CycleIter<'a, T> {
|
|||
}
|
||||
|
||||
pub fn cycle<T>(data: &[T]) -> CycleIter<'_, T> {
|
||||
CycleIter {
|
||||
index: 0,
|
||||
data,
|
||||
}
|
||||
CycleIter { index: 0, data }
|
||||
}
|
||||
|
||||
impl<'a, T> Iterator for CycleIter<'a, T> {
|
||||
|
@ -832,7 +833,9 @@ fn test_iterator_peekable_remember_peek_none_1() {
|
|||
let is_the_last = iter.peek().is_none();
|
||||
assert_eq!(is_the_last, n == data.len() - 1);
|
||||
n += 1;
|
||||
if n > data.len() { break; }
|
||||
if n > data.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert_eq!(n, data.len());
|
||||
}
|
||||
|
@ -914,7 +917,7 @@ fn test_iterator_skip() {
|
|||
while let Some(&x) = it.next() {
|
||||
assert_eq!(x, ys[i]);
|
||||
i += 1;
|
||||
assert_eq!(it.len(), xs.len()-5-i);
|
||||
assert_eq!(it.len(), xs.len() - 5 - i);
|
||||
}
|
||||
assert_eq!(i, ys.len());
|
||||
assert_eq!(it.len(), 0);
|
||||
|
@ -972,7 +975,6 @@ fn test_iterator_skip_nth() {
|
|||
|
||||
let mut it = xs.iter().skip(12);
|
||||
assert_eq!(it.nth(0), None);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1037,7 +1039,6 @@ fn test_iterator_skip_fold() {
|
|||
i
|
||||
});
|
||||
assert_eq!(i, 1);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1178,7 +1179,7 @@ fn test_iterator_flat_map() {
|
|||
fn test_iterator_flat_map_fold() {
|
||||
let xs = [0, 3, 6];
|
||||
let ys = [1, 2, 3, 4, 5, 6, 7];
|
||||
let mut it = xs.iter().flat_map(|&x| x..x+3);
|
||||
let mut it = xs.iter().flat_map(|&x| x..x + 3);
|
||||
assert_eq!(it.next(), Some(0));
|
||||
assert_eq!(it.next_back(), Some(8));
|
||||
let i = it.fold(0, |i, x| {
|
||||
|
@ -1187,7 +1188,7 @@ fn test_iterator_flat_map_fold() {
|
|||
});
|
||||
assert_eq!(i, ys.len());
|
||||
|
||||
let mut it = xs.iter().flat_map(|&x| x..x+3);
|
||||
let mut it = xs.iter().flat_map(|&x| x..x + 3);
|
||||
assert_eq!(it.next(), Some(0));
|
||||
assert_eq!(it.next_back(), Some(8));
|
||||
let i = it.rfold(ys.len(), |i, x| {
|
||||
|
@ -1216,7 +1217,7 @@ fn test_iterator_flatten() {
|
|||
fn test_iterator_flatten_fold() {
|
||||
let xs = [0, 3, 6];
|
||||
let ys = [1, 2, 3, 4, 5, 6, 7];
|
||||
let mut it = xs.iter().map(|&x| x..x+3).flatten();
|
||||
let mut it = xs.iter().map(|&x| x..x + 3).flatten();
|
||||
assert_eq!(it.next(), Some(0));
|
||||
assert_eq!(it.next_back(), Some(8));
|
||||
let i = it.fold(0, |i, x| {
|
||||
|
@ -1225,7 +1226,7 @@ fn test_iterator_flatten_fold() {
|
|||
});
|
||||
assert_eq!(i, ys.len());
|
||||
|
||||
let mut it = xs.iter().map(|&x| x..x+3).flatten();
|
||||
let mut it = xs.iter().map(|&x| x..x + 3).flatten();
|
||||
assert_eq!(it.next(), Some(0));
|
||||
assert_eq!(it.next_back(), Some(8));
|
||||
let i = it.rfold(ys.len(), |i, x| {
|
||||
|
@ -1240,10 +1241,7 @@ fn test_inspect() {
|
|||
let xs = [1, 2, 3, 4];
|
||||
let mut n = 0;
|
||||
|
||||
let ys = xs.iter()
|
||||
.cloned()
|
||||
.inspect(|_| n += 1)
|
||||
.collect::<Vec<usize>>();
|
||||
let ys = xs.iter().cloned().inspect(|_| n += 1).collect::<Vec<usize>>();
|
||||
|
||||
assert_eq!(n, xs.len());
|
||||
assert_eq!(&xs[..], &ys[..]);
|
||||
|
@ -1483,7 +1481,7 @@ fn test_iterator_size_hint() {
|
|||
assert_eq!(c.clone().enumerate().size_hint(), (usize::MAX, None));
|
||||
assert_eq!(c.clone().chain(vi.clone().cloned()).size_hint(), (usize::MAX, None));
|
||||
assert_eq!(c.clone().zip(vi.clone()).size_hint(), (10, Some(10)));
|
||||
assert_eq!(c.clone().scan(0, |_,_| Some(0)).size_hint(), (0, None));
|
||||
assert_eq!(c.clone().scan(0, |_, _| Some(0)).size_hint(), (0, None));
|
||||
assert_eq!(c.clone().filter(|_| false).size_hint(), (0, None));
|
||||
assert_eq!(c.clone().map(|_| 0).size_hint(), (usize::MAX, None));
|
||||
assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None));
|
||||
|
@ -1497,9 +1495,9 @@ fn test_iterator_size_hint() {
|
|||
assert_eq!(vi.clone().enumerate().size_hint(), (10, Some(10)));
|
||||
assert_eq!(vi.clone().chain(v2).size_hint(), (13, Some(13)));
|
||||
assert_eq!(vi.clone().zip(v2).size_hint(), (3, Some(3)));
|
||||
assert_eq!(vi.clone().scan(0, |_,_| Some(0)).size_hint(), (0, Some(10)));
|
||||
assert_eq!(vi.clone().scan(0, |_, _| Some(0)).size_hint(), (0, Some(10)));
|
||||
assert_eq!(vi.clone().filter(|_| false).size_hint(), (0, Some(10)));
|
||||
assert_eq!(vi.clone().map(|&i| i+1).size_hint(), (10, Some(10)));
|
||||
assert_eq!(vi.clone().map(|&i| i + 1).size_hint(), (10, Some(10)));
|
||||
assert_eq!(vi.filter_map(|_| Some(0)).size_hint(), (0, Some(10)));
|
||||
}
|
||||
|
||||
|
@ -1555,11 +1553,7 @@ fn test_find_map() {
|
|||
assert_eq!(iter.next(), Some(&7));
|
||||
|
||||
fn half_if_even(x: &isize) -> Option<isize> {
|
||||
if x % 2 == 0 {
|
||||
Some(x / 2)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if x % 2 == 0 { Some(x / 2) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1618,8 +1612,7 @@ fn test_rev() {
|
|||
let mut it = xs.iter();
|
||||
it.next();
|
||||
it.next();
|
||||
assert!(it.rev().cloned().collect::<Vec<isize>>() ==
|
||||
vec![16, 14, 12, 10, 8, 6]);
|
||||
assert!(it.rev().cloned().collect::<Vec<isize>>() == vec![16, 14, 12, 10, 8, 6]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1748,14 +1741,22 @@ fn test_double_ended_chain() {
|
|||
assert_eq!(it.next_back().unwrap(), &7);
|
||||
assert_eq!(it.next_back(), None);
|
||||
|
||||
|
||||
// test that .chain() is well behaved with an unfused iterator
|
||||
struct CrazyIterator(bool);
|
||||
impl CrazyIterator { fn new() -> CrazyIterator { CrazyIterator(false) } }
|
||||
impl CrazyIterator {
|
||||
fn new() -> CrazyIterator {
|
||||
CrazyIterator(false)
|
||||
}
|
||||
}
|
||||
impl Iterator for CrazyIterator {
|
||||
type Item = i32;
|
||||
fn next(&mut self) -> Option<i32> {
|
||||
if self.0 { Some(99) } else { self.0 = true; None }
|
||||
if self.0 {
|
||||
Some(99)
|
||||
} else {
|
||||
self.0 = true;
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1771,8 +1772,14 @@ fn test_double_ended_chain() {
|
|||
|
||||
#[test]
|
||||
fn test_rposition() {
|
||||
fn f(xy: &(isize, char)) -> bool { let (_x, y) = *xy; y == 'b' }
|
||||
fn g(xy: &(isize, char)) -> bool { let (_x, y) = *xy; y == 'd' }
|
||||
fn f(xy: &(isize, char)) -> bool {
|
||||
let (_x, y) = *xy;
|
||||
y == 'b'
|
||||
}
|
||||
fn g(xy: &(isize, char)) -> bool {
|
||||
let (_x, y) = *xy;
|
||||
y == 'd'
|
||||
}
|
||||
let v = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
|
||||
|
||||
assert_eq!(v.iter().rposition(f), Some(3));
|
||||
|
@ -1788,9 +1795,7 @@ fn test_rev_rposition() {
|
|||
#[test]
|
||||
#[should_panic]
|
||||
fn test_rposition_panic() {
|
||||
let v: [(Box<_>, Box<_>); 4] =
|
||||
[(box 0, box 0), (box 0, box 0),
|
||||
(box 0, box 0), (box 0, box 0)];
|
||||
let v: [(Box<_>, Box<_>); 4] = [(box 0, box 0), (box 0, box 0), (box 0, box 0), (box 0, box 0)];
|
||||
let mut i = 0;
|
||||
v.iter().rposition(|_elt| {
|
||||
if i == 2 {
|
||||
|
@ -1801,38 +1806,37 @@ fn test_rposition_panic() {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_double_ended_flat_map() {
|
||||
let u = [0,1];
|
||||
let v = [5,6,7,8];
|
||||
let u = [0, 1];
|
||||
let v = [5, 6, 7, 8];
|
||||
let mut it = u.iter().flat_map(|x| &v[*x..v.len()]);
|
||||
assert_eq!(it.next_back().unwrap(), &8);
|
||||
assert_eq!(it.next().unwrap(), &5);
|
||||
assert_eq!(it.next().unwrap(), &5);
|
||||
assert_eq!(it.next_back().unwrap(), &7);
|
||||
assert_eq!(it.next_back().unwrap(), &6);
|
||||
assert_eq!(it.next_back().unwrap(), &8);
|
||||
assert_eq!(it.next().unwrap(), &6);
|
||||
assert_eq!(it.next().unwrap(), &6);
|
||||
assert_eq!(it.next_back().unwrap(), &7);
|
||||
assert_eq!(it.next_back(), None);
|
||||
assert_eq!(it.next(), None);
|
||||
assert_eq!(it.next(), None);
|
||||
assert_eq!(it.next_back(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_double_ended_flatten() {
|
||||
let u = [0,1];
|
||||
let v = [5,6,7,8];
|
||||
let u = [0, 1];
|
||||
let v = [5, 6, 7, 8];
|
||||
let mut it = u.iter().map(|x| &v[*x..v.len()]).flatten();
|
||||
assert_eq!(it.next_back().unwrap(), &8);
|
||||
assert_eq!(it.next().unwrap(), &5);
|
||||
assert_eq!(it.next().unwrap(), &5);
|
||||
assert_eq!(it.next_back().unwrap(), &7);
|
||||
assert_eq!(it.next_back().unwrap(), &6);
|
||||
assert_eq!(it.next_back().unwrap(), &8);
|
||||
assert_eq!(it.next().unwrap(), &6);
|
||||
assert_eq!(it.next().unwrap(), &6);
|
||||
assert_eq!(it.next_back().unwrap(), &7);
|
||||
assert_eq!(it.next_back(), None);
|
||||
assert_eq!(it.next(), None);
|
||||
assert_eq!(it.next(), None);
|
||||
assert_eq!(it.next_back(), None);
|
||||
}
|
||||
|
||||
|
@ -1867,8 +1871,10 @@ fn test_range() {
|
|||
|
||||
assert_eq!((-70..58).size_hint(), (128, Some(128)));
|
||||
assert_eq!((-128..127).size_hint(), (255, Some(255)));
|
||||
assert_eq!((-2..isize::MAX).size_hint(),
|
||||
(isize::MAX as usize + 2, Some(isize::MAX as usize + 2)));
|
||||
assert_eq!(
|
||||
(-2..isize::MAX).size_hint(),
|
||||
(isize::MAX as usize + 2, Some(isize::MAX as usize + 2))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2171,15 +2177,15 @@ fn test_range_inclusive_folds() {
|
|||
assert!(it.is_empty());
|
||||
|
||||
let mut it = 10..=20;
|
||||
assert_eq!(it.try_fold(0, |a,b| Some(a+b)), Some(165));
|
||||
assert_eq!(it.try_fold(0, |a, b| Some(a + b)), Some(165));
|
||||
assert!(it.is_empty());
|
||||
assert_eq!(it.try_fold(0, |a,b| Some(a+b)), Some(0));
|
||||
assert_eq!(it.try_fold(0, |a, b| Some(a + b)), Some(0));
|
||||
assert!(it.is_empty());
|
||||
|
||||
let mut it = 10..=20;
|
||||
assert_eq!(it.try_rfold(0, |a,b| Some(a+b)), Some(165));
|
||||
assert_eq!(it.try_rfold(0, |a, b| Some(a + b)), Some(165));
|
||||
assert!(it.is_empty());
|
||||
assert_eq!(it.try_rfold(0, |a,b| Some(a+b)), Some(0));
|
||||
assert_eq!(it.try_rfold(0, |a, b| Some(a + b)), Some(0));
|
||||
assert!(it.is_empty());
|
||||
}
|
||||
|
||||
|
@ -2292,15 +2298,19 @@ fn test_repeat_with_take() {
|
|||
is_trusted_len(repeat_with(|| 42).take(3));
|
||||
assert_eq!(repeat_with(|| 42).take(3).size_hint(), (3, Some(3)));
|
||||
assert_eq!(repeat_with(|| 42).take(0).size_hint(), (0, Some(0)));
|
||||
assert_eq!(repeat_with(|| 42).take(usize::MAX).size_hint(),
|
||||
(usize::MAX, Some(usize::MAX)));
|
||||
assert_eq!(repeat_with(|| 42).take(usize::MAX).size_hint(), (usize::MAX, Some(usize::MAX)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_repeat_with_take_collect() {
|
||||
let mut curr = 1;
|
||||
let v: Vec<_> = repeat_with(|| { let tmp = curr; curr *= 2; tmp })
|
||||
.take(5).collect();
|
||||
let v: Vec<_> = repeat_with(|| {
|
||||
let tmp = curr;
|
||||
curr *= 2;
|
||||
tmp
|
||||
})
|
||||
.take(5)
|
||||
.collect();
|
||||
assert_eq!(v, vec![1, 2, 4, 8, 16]);
|
||||
}
|
||||
|
||||
|
@ -2472,7 +2482,7 @@ fn test_step_replace_no_between() {
|
|||
|
||||
#[test]
|
||||
fn test_rev_try_folds() {
|
||||
let f = &|acc, x| i32::checked_add(2*acc, x);
|
||||
let f = &|acc, x| i32::checked_add(2 * acc, x);
|
||||
assert_eq!((1..10).rev().try_fold(7, f), (1..10).try_rfold(7, f));
|
||||
assert_eq!((1..10).rev().try_rfold(7, f), (1..10).try_fold(7, f));
|
||||
|
||||
|
@ -2488,8 +2498,8 @@ fn test_rev_try_folds() {
|
|||
#[test]
|
||||
fn test_cloned_try_folds() {
|
||||
let a = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
let f = &|acc, x| i32::checked_add(2*acc, x);
|
||||
let f_ref = &|acc, &x| i32::checked_add(2*acc, x);
|
||||
let f = &|acc, x| i32::checked_add(2 * acc, x);
|
||||
let f_ref = &|acc, &x| i32::checked_add(2 * acc, x);
|
||||
assert_eq!(a.iter().cloned().try_fold(7, f), a.iter().try_fold(7, f_ref));
|
||||
assert_eq!(a.iter().cloned().try_rfold(7, f), a.iter().try_rfold(7, f_ref));
|
||||
|
||||
|
@ -2506,7 +2516,7 @@ fn test_cloned_try_folds() {
|
|||
fn test_chain_try_folds() {
|
||||
let c = || (0..10).chain(10..20);
|
||||
|
||||
let f = &|acc, x| i32::checked_add(2*acc, x);
|
||||
let f = &|acc, x| i32::checked_add(2 * acc, x);
|
||||
assert_eq!(c().try_fold(7, f), (0..20).try_fold(7, f));
|
||||
assert_eq!(c().try_rfold(7, f), (0..20).rev().try_fold(7, f));
|
||||
|
||||
|
@ -2515,14 +2525,14 @@ fn test_chain_try_folds() {
|
|||
assert_eq!(iter.next(), Some(6), "stopped in front, state Both");
|
||||
assert_eq!(iter.position(|x| x == 13), Some(6));
|
||||
assert_eq!(iter.next(), Some(14), "stopped in back, state Back");
|
||||
assert_eq!(iter.try_fold(0, |acc, x| Some(acc+x)), Some((15..20).sum()));
|
||||
assert_eq!(iter.try_fold(0, |acc, x| Some(acc + x)), Some((15..20).sum()));
|
||||
|
||||
let mut iter = c().rev(); // use rev to access try_rfold
|
||||
assert_eq!(iter.position(|x| x == 15), Some(4));
|
||||
assert_eq!(iter.next(), Some(14), "stopped in back, state Both");
|
||||
assert_eq!(iter.position(|x| x == 5), Some(8));
|
||||
assert_eq!(iter.next(), Some(4), "stopped in front, state Front");
|
||||
assert_eq!(iter.try_fold(0, |acc, x| Some(acc+x)), Some((0..4).sum()));
|
||||
assert_eq!(iter.try_fold(0, |acc, x| Some(acc + x)), Some((0..4).sum()));
|
||||
|
||||
let mut iter = c();
|
||||
iter.by_ref().rev().nth(14); // skip the last 15, ending in state Front
|
||||
|
@ -2535,11 +2545,11 @@ fn test_chain_try_folds() {
|
|||
|
||||
#[test]
|
||||
fn test_map_try_folds() {
|
||||
let f = &|acc, x| i32::checked_add(2*acc, x);
|
||||
assert_eq!((0..10).map(|x| x+3).try_fold(7, f), (3..13).try_fold(7, f));
|
||||
assert_eq!((0..10).map(|x| x+3).try_rfold(7, f), (3..13).try_rfold(7, f));
|
||||
let f = &|acc, x| i32::checked_add(2 * acc, x);
|
||||
assert_eq!((0..10).map(|x| x + 3).try_fold(7, f), (3..13).try_fold(7, f));
|
||||
assert_eq!((0..10).map(|x| x + 3).try_rfold(7, f), (3..13).try_rfold(7, f));
|
||||
|
||||
let mut iter = (0..40).map(|x| x+10);
|
||||
let mut iter = (0..40).map(|x| x + 10);
|
||||
assert_eq!(iter.try_fold(0, i8::checked_add), None);
|
||||
assert_eq!(iter.next(), Some(20));
|
||||
assert_eq!(iter.try_rfold(0, i8::checked_add), None);
|
||||
|
@ -2548,8 +2558,10 @@ fn test_map_try_folds() {
|
|||
|
||||
#[test]
|
||||
fn test_filter_try_folds() {
|
||||
fn p(&x: &i32) -> bool { 0 <= x && x < 10 }
|
||||
let f = &|acc, x| i32::checked_add(2*acc, x);
|
||||
fn p(&x: &i32) -> bool {
|
||||
0 <= x && x < 10
|
||||
}
|
||||
let f = &|acc, x| i32::checked_add(2 * acc, x);
|
||||
assert_eq!((-10..20).filter(p).try_fold(7, f), (0..10).try_fold(7, f));
|
||||
assert_eq!((-10..20).filter(p).try_rfold(7, f), (0..10).try_rfold(7, f));
|
||||
|
||||
|
@ -2562,12 +2574,12 @@ fn test_filter_try_folds() {
|
|||
|
||||
#[test]
|
||||
fn test_filter_map_try_folds() {
|
||||
let mp = &|x| if 0 <= x && x < 10 { Some(x*2) } else { None };
|
||||
let f = &|acc, x| i32::checked_add(2*acc, x);
|
||||
assert_eq!((-9..20).filter_map(mp).try_fold(7, f), (0..10).map(|x| 2*x).try_fold(7, f));
|
||||
assert_eq!((-9..20).filter_map(mp).try_rfold(7, f), (0..10).map(|x| 2*x).try_rfold(7, f));
|
||||
let mp = &|x| if 0 <= x && x < 10 { Some(x * 2) } else { None };
|
||||
let f = &|acc, x| i32::checked_add(2 * acc, x);
|
||||
assert_eq!((-9..20).filter_map(mp).try_fold(7, f), (0..10).map(|x| 2 * x).try_fold(7, f));
|
||||
assert_eq!((-9..20).filter_map(mp).try_rfold(7, f), (0..10).map(|x| 2 * x).try_rfold(7, f));
|
||||
|
||||
let mut iter = (0..40).filter_map(|x| if x%2 == 1 { None } else { Some(x*2 + 10) });
|
||||
let mut iter = (0..40).filter_map(|x| if x % 2 == 1 { None } else { Some(x * 2 + 10) });
|
||||
assert_eq!(iter.try_fold(0, i8::checked_add), None);
|
||||
assert_eq!(iter.next(), Some(38));
|
||||
assert_eq!(iter.try_rfold(0, i8::checked_add), None);
|
||||
|
@ -2576,9 +2588,9 @@ fn test_filter_map_try_folds() {
|
|||
|
||||
#[test]
|
||||
fn test_enumerate_try_folds() {
|
||||
let f = &|acc, (i, x)| usize::checked_add(2*acc, x/(i+1) + i);
|
||||
assert_eq!((9..18).enumerate().try_fold(7, f), (0..9).map(|i| (i, i+9)).try_fold(7, f));
|
||||
assert_eq!((9..18).enumerate().try_rfold(7, f), (0..9).map(|i| (i, i+9)).try_rfold(7, f));
|
||||
let f = &|acc, (i, x)| usize::checked_add(2 * acc, x / (i + 1) + i);
|
||||
assert_eq!((9..18).enumerate().try_fold(7, f), (0..9).map(|i| (i, i + 9)).try_fold(7, f));
|
||||
assert_eq!((9..18).enumerate().try_rfold(7, f), (0..9).map(|i| (i, i + 9)).try_rfold(7, f));
|
||||
|
||||
let mut iter = (100..200).enumerate();
|
||||
let f = &|acc, (i, x)| u8::checked_add(acc, u8::checked_div(x, i as u8 + 1)?);
|
||||
|
@ -2590,7 +2602,7 @@ fn test_enumerate_try_folds() {
|
|||
|
||||
#[test]
|
||||
fn test_peek_try_folds() {
|
||||
let f = &|acc, x| i32::checked_add(2*acc, x);
|
||||
let f = &|acc, x| i32::checked_add(2 * acc, x);
|
||||
|
||||
assert_eq!((1..20).peekable().try_fold(7, f), (1..20).try_fold(7, f));
|
||||
assert_eq!((1..20).peekable().try_rfold(7, f), (1..20).try_rfold(7, f));
|
||||
|
@ -2637,8 +2649,10 @@ fn test_peek_try_folds() {
|
|||
|
||||
#[test]
|
||||
fn test_skip_while_try_fold() {
|
||||
let f = &|acc, x| i32::checked_add(2*acc, x);
|
||||
fn p(&x: &i32) -> bool { (x % 10) <= 5 }
|
||||
let f = &|acc, x| i32::checked_add(2 * acc, x);
|
||||
fn p(&x: &i32) -> bool {
|
||||
(x % 10) <= 5
|
||||
}
|
||||
assert_eq!((1..20).skip_while(p).try_fold(7, f), (6..20).try_fold(7, f));
|
||||
let mut iter = (1..20).skip_while(p);
|
||||
assert_eq!(iter.nth(5), Some(11));
|
||||
|
@ -2651,13 +2665,13 @@ fn test_skip_while_try_fold() {
|
|||
|
||||
#[test]
|
||||
fn test_take_while_folds() {
|
||||
let f = &|acc, x| i32::checked_add(2*acc, x);
|
||||
let f = &|acc, x| i32::checked_add(2 * acc, x);
|
||||
assert_eq!((1..20).take_while(|&x| x != 10).try_fold(7, f), (1..10).try_fold(7, f));
|
||||
let mut iter = (1..20).take_while(|&x| x != 10);
|
||||
assert_eq!(iter.try_fold(0, |x, y| Some(x+y)), Some((1..10).sum()));
|
||||
assert_eq!(iter.try_fold(0, |x, y| Some(x + y)), Some((1..10).sum()));
|
||||
assert_eq!(iter.next(), None, "flag should be set");
|
||||
let iter = (1..20).take_while(|&x| x != 10);
|
||||
assert_eq!(iter.fold(0, |x, y| x+y), (1..10).sum());
|
||||
assert_eq!(iter.fold(0, |x, y| x + y), (1..10).sum());
|
||||
|
||||
let mut iter = (10..50).take_while(|&x| x != 40);
|
||||
assert_eq!(iter.try_fold(0, i8::checked_add), None);
|
||||
|
@ -2666,7 +2680,7 @@ fn test_take_while_folds() {
|
|||
|
||||
#[test]
|
||||
fn test_skip_try_folds() {
|
||||
let f = &|acc, x| i32::checked_add(2*acc, x);
|
||||
let f = &|acc, x| i32::checked_add(2 * acc, x);
|
||||
assert_eq!((1..20).skip(9).try_fold(7, f), (10..20).try_fold(7, f));
|
||||
assert_eq!((1..20).skip(9).try_rfold(7, f), (10..20).try_rfold(7, f));
|
||||
|
||||
|
@ -2713,7 +2727,7 @@ fn test_skip_nth_back() {
|
|||
|
||||
#[test]
|
||||
fn test_take_try_folds() {
|
||||
let f = &|acc, x| i32::checked_add(2*acc, x);
|
||||
let f = &|acc, x| i32::checked_add(2 * acc, x);
|
||||
assert_eq!((10..30).take(10).try_fold(7, f), (10..20).try_fold(7, f));
|
||||
assert_eq!((10..30).take(10).try_rfold(7, f), (10..20).try_rfold(7, f));
|
||||
|
||||
|
@ -2738,15 +2752,16 @@ fn test_take_try_folds() {
|
|||
|
||||
#[test]
|
||||
fn test_flat_map_try_folds() {
|
||||
let f = &|acc, x| i32::checked_add(acc*2/3, x);
|
||||
let mr = &|x| (5*x)..(5*x + 5);
|
||||
let f = &|acc, x| i32::checked_add(acc * 2 / 3, x);
|
||||
let mr = &|x| (5 * x)..(5 * x + 5);
|
||||
assert_eq!((0..10).flat_map(mr).try_fold(7, f), (0..50).try_fold(7, f));
|
||||
assert_eq!((0..10).flat_map(mr).try_rfold(7, f), (0..50).try_rfold(7, f));
|
||||
let mut iter = (0..10).flat_map(mr);
|
||||
iter.next(); iter.next_back(); // have front and back iters in progress
|
||||
iter.next();
|
||||
iter.next_back(); // have front and back iters in progress
|
||||
assert_eq!(iter.try_rfold(7, f), (1..49).try_rfold(7, f));
|
||||
|
||||
let mut iter = (0..10).flat_map(|x| (4*x)..(4*x + 4));
|
||||
let mut iter = (0..10).flat_map(|x| (4 * x)..(4 * x + 4));
|
||||
assert_eq!(iter.try_fold(0, i8::checked_add), None);
|
||||
assert_eq!(iter.next(), Some(17));
|
||||
assert_eq!(iter.try_rfold(0, i8::checked_add), None);
|
||||
|
@ -2755,15 +2770,16 @@ fn test_flat_map_try_folds() {
|
|||
|
||||
#[test]
|
||||
fn test_flatten_try_folds() {
|
||||
let f = &|acc, x| i32::checked_add(acc*2/3, x);
|
||||
let mr = &|x| (5*x)..(5*x + 5);
|
||||
let f = &|acc, x| i32::checked_add(acc * 2 / 3, x);
|
||||
let mr = &|x| (5 * x)..(5 * x + 5);
|
||||
assert_eq!((0..10).map(mr).flatten().try_fold(7, f), (0..50).try_fold(7, f));
|
||||
assert_eq!((0..10).map(mr).flatten().try_rfold(7, f), (0..50).try_rfold(7, f));
|
||||
let mut iter = (0..10).map(mr).flatten();
|
||||
iter.next(); iter.next_back(); // have front and back iters in progress
|
||||
iter.next();
|
||||
iter.next_back(); // have front and back iters in progress
|
||||
assert_eq!(iter.try_rfold(7, f), (1..49).try_rfold(7, f));
|
||||
|
||||
let mut iter = (0..10).map(|x| (4*x)..(4*x + 4)).flatten();
|
||||
let mut iter = (0..10).map(|x| (4 * x)..(4 * x + 4)).flatten();
|
||||
assert_eq!(iter.try_fold(0, i8::checked_add), None);
|
||||
assert_eq!(iter.next(), Some(17));
|
||||
assert_eq!(iter.try_rfold(0, i8::checked_add), None);
|
||||
|
@ -2773,13 +2789,21 @@ fn test_flatten_try_folds() {
|
|||
#[test]
|
||||
fn test_functor_laws() {
|
||||
// identity:
|
||||
fn identity<T>(x: T) -> T { x }
|
||||
fn identity<T>(x: T) -> T {
|
||||
x
|
||||
}
|
||||
assert_eq!((0..10).map(identity).sum::<usize>(), (0..10).sum());
|
||||
|
||||
// composition:
|
||||
fn f(x: usize) -> usize { x + 3 }
|
||||
fn g(x: usize) -> usize { x * 2 }
|
||||
fn h(x: usize) -> usize { g(f(x)) }
|
||||
fn f(x: usize) -> usize {
|
||||
x + 3
|
||||
}
|
||||
fn g(x: usize) -> usize {
|
||||
x * 2
|
||||
}
|
||||
fn h(x: usize) -> usize {
|
||||
g(f(x))
|
||||
}
|
||||
assert_eq!((0..10).map(f).map(g).sum::<usize>(), (0..10).map(h).sum());
|
||||
}
|
||||
|
||||
|
@ -2798,10 +2822,16 @@ fn test_monad_laws_right_identity() {
|
|||
|
||||
#[test]
|
||||
fn test_monad_laws_associativity() {
|
||||
fn f(x: usize) -> impl Iterator<Item = usize> { 0..x }
|
||||
fn g(x: usize) -> impl Iterator<Item = usize> { (0..x).rev() }
|
||||
assert_eq!((0..10).flat_map(f).flat_map(g).sum::<usize>(),
|
||||
(0..10).flat_map(|x| f(x).flat_map(g)).sum::<usize>());
|
||||
fn f(x: usize) -> impl Iterator<Item = usize> {
|
||||
0..x
|
||||
}
|
||||
fn g(x: usize) -> impl Iterator<Item = usize> {
|
||||
(0..x).rev()
|
||||
}
|
||||
assert_eq!(
|
||||
(0..10).flat_map(f).flat_map(g).sum::<usize>(),
|
||||
(0..10).flat_map(|x| f(x).flat_map(g)).sum::<usize>()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -32,7 +32,8 @@ fn ordinary() {
|
|||
test_literal!(12345.);
|
||||
test_literal!(0.9999999);
|
||||
|
||||
if cfg!(miri) { // Miri is too slow
|
||||
if cfg!(miri) {
|
||||
// Miri is too slow
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -82,7 +83,8 @@ fn zero() {
|
|||
test_literal!(0.0);
|
||||
test_literal!(1e-325);
|
||||
|
||||
if cfg!(miri) { // Miri is too slow
|
||||
if cfg!(miri) {
|
||||
// Miri is too slow
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue