Format the world

This commit is contained in:
Mark Rousskov 2019-12-22 17:42:04 -05:00
parent 8eb7c58dbb
commit a06baa56b9
1160 changed files with 65934 additions and 74316 deletions

View File

@ -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();

View File

@ -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<_>>();

View File

@ -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),

View File

@ -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);
}

View File

@ -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

View File

@ -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());

View File

@ -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(),

View File

@ -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();

View File

@ -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);

View File

@ -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(),

View File

@ -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")
}

View File

@ -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));

View File

@ -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()
}

View File

@ -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

View File

@ -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))?;
}
}

View File

@ -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,
}
}

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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");
}
}

View File

@ -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!"
);
}
}
}

View File

@ -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

View File

@ -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) {

View File

@ -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(&current_toolstate));

View File

@ -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"))
}

View File

@ -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"), &timestamp) || !up_to_date(src_dir, &timestamp) {
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))
}

View File

@ -1,7 +1,7 @@
mod _common;
use std::char;
use _common::validate;
use std::char;
fn main() {
for n in 0..10 {

View File

@ -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);

View File

@ -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) {

View File

@ -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) }
}
}

View File

@ -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;

View File

@ -1,5 +1,5 @@
use std::iter::{repeat, FromIterator};
use test::Bencher;
use std::iter::{FromIterator, repeat};
#[bench]
fn bench_new(b: &mut Bencher) {

View File

@ -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) {

View File

@ -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> {

View File

@ -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> {}

View File

@ -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

View File

@ -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);

View File

@ -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()
}
}

View File

@ -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 allocators 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 {

View File

@ -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);

View File

@ -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))]

View File

@ -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();
}
}
}

View File

@ -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`.

View File

@ -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);

View File

@ -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,

View File

@ -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
}

View File

@ -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 {

View File

@ -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);

View File

@ -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

View File

@ -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);
}
};
}

View File

@ -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;
}

View File

@ -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

View File

@ -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();

View File

@ -531,7 +531,6 @@ fn drain_filter_complex() {
}
}
#[test]
fn test_drop() {
static mut DROPS: i32 = 0;

View File

@ -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]);
}

View File

@ -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}\u{e000}".escape_debug().to_string(),
"\\u{301}a\u{301}\\u{e000}");
assert_eq!(
"\u{301}a\u{301}\u{e000}".escape_debug().to_string(),
"\\u{301}a\u{301}\\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);
}

View File

@ -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!")
}
}
}

View File

@ -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)]

View File

@ -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()` didnt 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

View File

@ -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)

View File

@ -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] });
})
}

View File

@ -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),
}
}
}

View File

@ -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>() }
}
}

View File

@ -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()
}
}

View File

@ -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}

View File

@ -21,7 +21,6 @@ fn starts_with_str(b: &mut Bencher) {
})
}
#[bench]
fn ends_with_char(b: &mut Bencher) {
let text = black_box("kdjsfhlakfhlsghlkvcnljknfqiunvcijqenwodind");

View File

@ -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
}
}

View File

@ -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,
}
}

View File

@ -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)
}
}
}

View File

@ -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);

View File

@ -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\

View File

@ -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
}

View File

@ -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>,
{
}

View File

@ -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.

View File

@ -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> {

View File

@ -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();

View File

@ -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 {}

View File

@ -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};

View File

@ -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;

View File

@ -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 {}
}

View File

@ -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

View File

@ -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()
}
}

View File

@ -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)
}

View File

@ -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 }

View File

@ -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
}
}

View File

@ -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;

View File

@ -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
}
}

View File

@ -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

View File

@ -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.
{

View File

@ -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>,
>,
}

View File

@ -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)
}
}

View File

@ -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 {

View File

@ -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 });
}

View File

@ -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()
);
}

View File

@ -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;
}

View File

@ -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]

View File

@ -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