Merge branch 'master' into redox_builder

This commit is contained in:
Artyom Pavlov 2019-08-17 18:54:56 +00:00 committed by GitHub
commit 51dcdcfd94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
497 changed files with 6928 additions and 3474 deletions

View File

@ -106,7 +106,7 @@ dependencies = [
"cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-std-workspace-core 1.0.0",
]
@ -1138,19 +1138,12 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.4.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-std-workspace-alloc 1.0.0",
"rustc-std-workspace-core 1.0.0",
]
[[package]]
name = "hashbrown"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2736,7 +2729,7 @@ dependencies = [
[[package]]
name = "rustc-demangle"
version = "0.1.15"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2894,7 +2887,7 @@ dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"punycode 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_data_structures 0.0.0",
"rustc_metadata 0.0.0",
"rustc_target 0.0.0",
@ -3534,8 +3527,9 @@ dependencies = [
"core 0.0.0",
"dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"hashbrown 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.61 (registry+https://github.com/rust-lang/crates.io-index)",
"hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"panic_abort 0.0.0",
"panic_unwind 0.0.0",
"profiler_builtins 0.0.0",
@ -4450,7 +4444,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4feaabe24a0a658fd9cf4a9acf6ed284f045c77df0f49020ba3245cfb7b454"
"checksum h2 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "a539b63339fbbb00e081e84b6e11bd1d9634a82d91da2984a18ac74a8823f392"
"checksum handlebars 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "df044dd42cdb7e32f28557b661406fc0f2494be75199779998810dbc35030e0d"
"checksum hashbrown 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9529213c67695ca2d146e6f263b7b72df8fa973368beadf767e8ed80c03f2f36"
"checksum hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353"
"checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82"
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
@ -4600,7 +4593,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61673783f2089e01033ffa82d1988f55175402071b31253a358292e1624d4602"
"checksum rustc-ap-syntax 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28f3dd1346d5b0269c07a4a78855e309a298ab569c9c1302d4d4f57f8eee4e84"
"checksum rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45e67b526dbda3a0c7dab91c8947d43685e7697f52686a4949da3c179cd7c979"
"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
"checksum rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363"
"checksum rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79d38ca7cbc22fa59f09d8534ea4b27f67b0facf0cbe274433aceea227a02543"

View File

@ -144,7 +144,7 @@ then you may need to force rustbuild to use an older version. This can be done
by manually calling the appropriate vcvars file before running the bootstrap.
```batch
> CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
> CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
> python x.py build
```

View File

@ -22,7 +22,7 @@ Language
- [You can now use `_` as an identifier for consts.][61347] e.g. You can write
`const _: u32 = 5;`.
- [You can now use `#[repr(align(X)]` on enums.][61229]
- [The `?`/_"Kleene"_ macro operator is now available in the
- [The `?` Kleene macro operator is now available in the
2015 edition.][60932]
Compiler

View File

@ -141,10 +141,10 @@
# library and facade crates.
#compiler-docs = false
# Indicate whether submodules are managed and updated automatically.
# Indicate whether git submodules are managed and updated automatically.
#submodules = true
# Update submodules only when the checked out commit in the submodules differs
# Update git submodules only when the checked out commit in the submodules differs
# from what is committed in the main rustc repo.
#fast-submodules = true

View File

@ -37,7 +37,7 @@ fn main() {
let mut new = None;
if let Some(current_as_str) = args[i].to_str() {
if (&*args[i - 1] == "-C" && current_as_str.starts_with("metadata")) ||
current_as_str.starts_with("-Cmetadata") {
current_as_str.starts_with("-Cmetadata") {
new = Some(format!("{}-{}", current_as_str, s));
}
}
@ -45,18 +45,6 @@ fn main() {
}
}
// Drop `--error-format json` because despite our desire for json messages
// from Cargo we don't want any from rustc itself.
if let Some(n) = args.iter().position(|n| n == "--error-format") {
args.remove(n);
args.remove(n);
}
if let Some(s) = env::var_os("RUSTC_ERROR_FORMAT") {
args.push("--error-format".into());
args.push(s);
}
// Detect whether or not we're a build script depending on whether --target
// is passed (a bit janky...)
let target = args.windows(2)
@ -101,7 +89,7 @@ fn main() {
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)
target.into_string().unwrap().split(",").any(|c| c.trim() == crate_name)
{
cmd.arg("-Ztime");
}
@ -110,8 +98,17 @@ fn main() {
// Non-zero stages must all be treated uniformly to avoid problems when attempting to uplift
// compiler libraries and such from stage 1 to 2.
//
// FIXME: the fact that core here is excluded is due to core_arch from our stdarch submodule
// being broken on the beta compiler with bootstrap passed, so this is a temporary workaround
// (we've just snapped, so there are no cfg(bootstrap) related annotations in core).
if stage == "0" {
cmd.arg("--cfg").arg("bootstrap");
if crate_name != Some("core") {
cmd.arg("--cfg").arg("bootstrap");
} else {
// NOTE(eddyb) see FIXME above, except now we need annotations again in core.
cmd.arg("--cfg").arg("boostrap_stdarch_ignore_this");
}
}
// Print backtrace in case of ICE
@ -132,10 +129,7 @@ fn main() {
cmd.arg("-Dwarnings");
cmd.arg("-Drust_2018_idioms");
cmd.arg("-Dunused_lifetimes");
// cfg(not(bootstrap)): Remove this during the next stage 0 compiler update.
// `-Drustc::internal` is a new feature and `rustc_version` mis-reports the `stage`.
let cfg_not_bootstrap = stage != "0" && crate_name != Some("rustc_version");
if cfg_not_bootstrap && use_internal_lints(crate_name) {
if use_internal_lints(crate_name) {
cmd.arg("-Zunstable-options");
cmd.arg("-Drustc::internal");
}
@ -287,10 +281,6 @@ fn main() {
cmd.arg("-C").arg("target-feature=-crt-static");
}
}
if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
cmd.arg("--remap-path-prefix").arg(&map);
}
} else {
// Override linker if necessary.
if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") {
@ -307,6 +297,10 @@ fn main() {
}
}
if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
cmd.arg("--remap-path-prefix").arg(&map);
}
// Force all crates compiled by this compiler to (a) be unstable and (b)
// allow the `rustc_private` feature to link to other unstable crates
// also in the sysroot. We also do this for host crates, since those

View File

@ -145,7 +145,7 @@ impl StepDescription {
only_hosts: S::ONLY_HOSTS,
should_run: S::should_run,
make_run: S::make_run,
name: unsafe { ::std::intrinsics::type_name::<S>() },
name: std::any::type_name::<S>(),
}
}
@ -754,76 +754,20 @@ impl<'a> Builder<'a> {
let mut cargo = Command::new(&self.initial_cargo);
let out_dir = self.stage_out(compiler, mode);
// command specific path, we call clear_if_dirty with this
let mut my_out = match cmd {
"build" => self.cargo_out(compiler, mode, target),
// This is the intended out directory for crate documentation.
"doc" | "rustdoc" => self.crate_doc_out(target),
_ => self.stage_out(compiler, mode),
};
// This is for the original compiler, but if we're forced to use stage 1, then
// std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since
// we copy the libs forward.
let cmp = self.compiler_for(compiler.stage, compiler.host, target);
let libstd_stamp = match cmd {
"check" | "clippy" | "fix" => check::libstd_stamp(self, cmp, target),
_ => compile::libstd_stamp(self, cmp, target),
};
let libtest_stamp = match cmd {
"check" | "clippy" | "fix" => check::libtest_stamp(self, cmp, target),
_ => compile::libtest_stamp(self, cmp, target),
};
let librustc_stamp = match cmd {
"check" | "clippy" | "fix" => check::librustc_stamp(self, cmp, target),
_ => compile::librustc_stamp(self, cmp, target),
};
// Codegen backends are not yet tracked by -Zbinary-dep-depinfo,
// so we need to explicitly clear out if they've been updated.
for backend in self.codegen_backends(compiler) {
self.clear_if_dirty(&out_dir, &backend);
}
if cmd == "doc" || cmd == "rustdoc" {
if mode == Mode::Rustc || mode == Mode::ToolRustc || mode == Mode::Codegen {
let my_out = match mode {
// This is the intended out directory for compiler documentation.
my_out = self.compiler_doc_out(target);
}
Mode::Rustc | Mode::ToolRustc | Mode::Codegen => self.compiler_doc_out(target),
_ => self.crate_doc_out(target),
};
let rustdoc = self.rustdoc(compiler);
self.clear_if_dirty(&my_out, &rustdoc);
} else if cmd != "test" {
match mode {
Mode::Std => {
self.clear_if_dirty(&my_out, &self.rustc(compiler));
for backend in self.codegen_backends(compiler) {
self.clear_if_dirty(&my_out, &backend);
}
},
Mode::Test => {
self.clear_if_dirty(&my_out, &libstd_stamp);
},
Mode::Rustc => {
self.clear_if_dirty(&my_out, &self.rustc(compiler));
self.clear_if_dirty(&my_out, &libstd_stamp);
self.clear_if_dirty(&my_out, &libtest_stamp);
},
Mode::Codegen => {
self.clear_if_dirty(&my_out, &librustc_stamp);
},
Mode::ToolBootstrap => { },
Mode::ToolStd => {
self.clear_if_dirty(&my_out, &libstd_stamp);
},
Mode::ToolTest => {
self.clear_if_dirty(&my_out, &libstd_stamp);
self.clear_if_dirty(&my_out, &libtest_stamp);
},
Mode::ToolRustc => {
self.clear_if_dirty(&my_out, &libstd_stamp);
self.clear_if_dirty(&my_out, &libtest_stamp);
self.clear_if_dirty(&my_out, &librustc_stamp);
},
}
}
cargo
@ -861,6 +805,19 @@ impl<'a> Builder<'a> {
},
}
// This tells Cargo (and in turn, rustc) to output more complete
// dependency information. Most importantly for rustbuild, this
// includes sysroot artifacts, like libstd, which means that we don't
// need to track those in rustbuild (an error prone process!). This
// feature is currently unstable as there may be some bugs and such, but
// it represents a big improvement in rustbuild's reliability on
// rebuilds, so we're using it here.
//
// For some additional context, see #63470 (the PR originally adding
// this), as well as #63012 which is the tracking issue for this
// feature on the rustc side.
cargo.arg("-Zbinary-dep-depinfo");
cargo.arg("-j").arg(self.jobs().to_string());
// Remove make-related flags to ensure Cargo can correctly set things up
cargo.env_remove("MAKEFLAGS");
@ -980,9 +937,6 @@ impl<'a> Builder<'a> {
if let Some(target_linker) = self.linker(target) {
cargo.env("RUSTC_TARGET_LINKER", target_linker);
}
if let Some(ref error_format) = self.config.rustc_error_format {
cargo.env("RUSTC_ERROR_FORMAT", error_format);
}
if !(["build", "check", "clippy", "fix", "rustc"].contains(&cmd)) && want_rustdoc {
cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler));
}

View File

@ -46,7 +46,7 @@ fn cc2ar(cc: &Path, target: &str) -> Option<PathBuf> {
} else if target.contains("openbsd") {
Some(PathBuf::from("ar"))
} else if target.contains("vxworks") {
Some(PathBuf::from("vx-ar"))
Some(PathBuf::from("wr-ar"))
} else {
let parent = cc.parent().unwrap();
let file = cc.file_name().unwrap().to_str().unwrap();

View File

@ -13,7 +13,7 @@ use build_helper::output;
use crate::Build;
// The version number
pub const CFG_RELEASE_NUM: &str = "1.38.0";
pub const CFG_RELEASE_NUM: &str = "1.39.0";
pub struct GitInfo {
inner: Option<Info>,

View File

@ -245,7 +245,6 @@ impl Step for Rustdoc {
let libdir = builder.sysroot_libdir(compiler, target);
let hostdir = builder.sysroot_libdir(compiler, compiler.host);
add_to_sysroot(&builder, &libdir, &hostdir, &rustdoc_stamp(builder, compiler, target));
builder.cargo(compiler, Mode::ToolRustc, target, "clean");
}
}

View File

@ -15,7 +15,7 @@ use std::path::{Path, PathBuf};
use std::process::{Command, Stdio, exit};
use std::str;
use build_helper::{output, mtime, t, up_to_date};
use build_helper::{output, t, up_to_date};
use filetime::FileTime;
use serde::Deserialize;
use serde_json;
@ -274,8 +274,6 @@ impl Step for StdLink {
// for reason why the sanitizers are not built in stage0.
copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir);
}
builder.cargo(target_compiler, Mode::ToolStd, target, "clean");
}
}
@ -480,8 +478,6 @@ impl Step for TestLink {
&builder.sysroot_libdir(target_compiler, compiler.host),
&libtest_stamp(builder, compiler, target)
);
builder.cargo(target_compiler, Mode::ToolTest, target, "clean");
}
}
@ -639,7 +635,6 @@ impl Step for RustcLink {
&builder.sysroot_libdir(target_compiler, compiler.host),
&librustc_stamp(builder, compiler, target)
);
builder.cargo(target_compiler, Mode::ToolRustc, target, "clean");
}
}
@ -795,6 +790,9 @@ pub fn build_codegen_backend(builder: &Builder<'_>,
if builder.config.llvm_use_libcxx {
cargo.env("LLVM_USE_LIBCXX", "1");
}
if builder.config.llvm_optimize && !builder.config.llvm_release_debuginfo {
cargo.env("LLVM_NDEBUG", "1");
}
}
_ => panic!("unknown backend: {}", backend),
}
@ -1116,10 +1114,6 @@ pub fn run_cargo(builder: &Builder<'_>,
},
..
} => (filenames, crate_types),
CargoMessage::CompilerMessage { message } => {
eprintln!("{}", message.rendered);
return;
}
_ => return,
};
for filename in filenames {
@ -1206,41 +1200,13 @@ pub fn run_cargo(builder: &Builder<'_>,
deps.push((path_to_add.into(), false));
}
// Now we want to update the contents of the stamp file, if necessary. First
// we read off the previous contents along with its mtime. If our new
// contents (the list of files to copy) is different or if any dep's mtime
// is newer then we rewrite the stamp file.
deps.sort();
let stamp_contents = fs::read(stamp);
let stamp_mtime = mtime(&stamp);
let mut new_contents = Vec::new();
let mut max = None;
let mut max_path = None;
for (dep, proc_macro) in deps.iter() {
let mtime = mtime(dep);
if Some(mtime) > max {
max = Some(mtime);
max_path = Some(dep.clone());
}
new_contents.extend(if *proc_macro { b"h" } else { b"t" });
new_contents.extend(dep.to_str().unwrap().as_bytes());
new_contents.extend(b"\0");
}
let max = max.unwrap();
let max_path = max_path.unwrap();
let contents_equal = stamp_contents
.map(|contents| contents == new_contents)
.unwrap_or_default();
if contents_equal && max <= stamp_mtime {
builder.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}",
stamp, max, stamp_mtime));
return deps.into_iter().map(|(d, _)| d).collect()
}
if max > stamp_mtime {
builder.verbose(&format!("updating {:?} as {:?} changed", stamp, max_path));
} else {
builder.verbose(&format!("updating {:?} as deps changed", stamp));
}
t!(fs::write(&stamp, &new_contents));
deps.into_iter().map(|(d, _)| d).collect()
}
@ -1256,8 +1222,12 @@ 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.
cargo.arg("--message-format").arg("json")
.stdout(Stdio::piped());
let mut message_format = String::from("json-render-diagnostics");
if let Some(s) = &builder.config.rustc_error_format {
message_format.push_str(",json-diagnostic-");
message_format.push_str(s);
}
cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped());
for arg in tail_args {
cargo.arg(arg);
@ -1310,12 +1280,4 @@ pub enum CargoMessage<'a> {
BuildScriptExecuted {
package_id: Cow<'a, str>,
},
CompilerMessage {
message: ClippyMessage<'a>
}
}
#[derive(Deserialize)]
pub struct ClippyMessage<'a> {
rendered: Cow<'a, str>,
}

View File

@ -81,5 +81,14 @@ ci-subset-1:
ci-subset-2:
$(Q)$(BOOTSTRAP) test $(TESTS_IN_2)
TESTS_IN_MINGW_2 := \
src/test/ui \
src/test/compile-fail
ci-mingw-subset-1:
$(Q)$(BOOTSTRAP) test $(TESTS_IN_MINGW_2:%=--exclude %)
ci-mingw-subset-2:
$(Q)$(BOOTSTRAP) test $(TESTS_IN_MINGW_2)
.PHONY: dist

View File

@ -202,10 +202,6 @@ pub fn check(build: &mut Build) {
panic!("couldn't find libc.a in musl dir: {}",
root.join("lib").display());
}
if fs::metadata(root.join("lib/libunwind.a")).is_err() {
panic!("couldn't find libunwind.a in musl dir: {}",
root.join("lib").display());
}
}
None => {
panic!("when targeting MUSL either the rust.musl-root \

View File

@ -272,8 +272,8 @@ jobs:
i686-mingw-1:
MSYS_BITS: 32
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
SCRIPT: make ci-subset-1
MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror
SCRIPT: make ci-mingw-subset-1
MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc
MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
MINGW_DIR: mingw32
# FIXME(#59637)
@ -282,15 +282,15 @@ jobs:
i686-mingw-2:
MSYS_BITS: 32
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
SCRIPT: make ci-subset-2
MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror
SCRIPT: make ci-mingw-subset-2
MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc
MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
MINGW_DIR: mingw32
x86_64-mingw-1:
MSYS_BITS: 64
SCRIPT: make ci-subset-1
SCRIPT: make ci-mingw-subset-1
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror
MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc
MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z
MINGW_DIR: mingw64
# FIXME(#59637)
@ -298,9 +298,9 @@ jobs:
NO_LLVM_ASSERTIONS: 1
x86_64-mingw-2:
MSYS_BITS: 64
SCRIPT: make ci-subset-2
SCRIPT: make ci-mingw-subset-2
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror
MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc
MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z
MINGW_DIR: mingw64
@ -327,7 +327,7 @@ jobs:
MSYS_BITS: 32
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools --enable-profiler
SCRIPT: python x.py dist
MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror
MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc
MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
MINGW_DIR: mingw32
DIST_REQUIRE_ALL_TOOLS: 1
@ -336,7 +336,7 @@ jobs:
MSYS_BITS: 64
SCRIPT: python x.py dist
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler
MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror
MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc
MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z
MINGW_DIR: mingw64
DIST_REQUIRE_ALL_TOOLS: 1

View File

@ -36,7 +36,7 @@ steps:
set -e
mkdir -p citools
cd citools
curl -f https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/LLVM-7.0.0-win64.tar.gz | tar xzf -
curl -f https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/LLVM-7.0.0-win64.tar.gz | tar xzf -
echo "##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]$RUST_CONFIGURE_ARGS --set llvm.clang-cl=`pwd`/clang-rust/bin/clang-cl.exe"
condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), eq(variables['MINGW_URL'],''))
displayName: Install clang (Windows)

View File

@ -2,14 +2,14 @@ steps:
- bash: |
set -e
curl -fo /usr/local/bin/sccache https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-02-sccache-x86_64-apple-darwin
curl -fo /usr/local/bin/sccache https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2018-04-02-sccache-x86_64-apple-darwin
chmod +x /usr/local/bin/sccache
displayName: Install sccache (OSX)
condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin'))
- script: |
md sccache
powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf sccache\sccache.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc"
powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf sccache\sccache.exe https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2018-04-26-sccache-x86_64-pc-windows-msvc"
echo ##vso[task.prependpath]%CD%\sccache
displayName: Install sccache (Windows)
condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))

View File

@ -4,7 +4,7 @@ steps:
# https://github.com/wixtoolset/wix3 originally
- bash: |
set -e
curl -O https://rust-lang-ci2.s3-us-west-1.amazonaws.com/rust-ci-mirror/wix311-binaries.zip
curl -O https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/wix311-binaries.zip
echo "##vso[task.setvariable variable=WIX]`pwd`/wix"
mkdir -p wix/bin
cd wix/bin
@ -18,7 +18,7 @@ steps:
# one is MSI installers and one is EXE, but they're not used so frequently at
# this point anyway so perhaps it's a wash!
- script: |
powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf is-install.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-08-22-is.exe"
powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf is-install.exe https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2017-08-22-is.exe"
is-install.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
echo ##vso[task.prependpath]C:\Program Files (x86)\Inno Setup 5
displayName: Install InnoSetup
@ -109,7 +109,7 @@ steps:
# Note that this is originally from the github releases patch of Ninja
- script: |
md ninja
powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-03-15-ninja-win.zip https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-03-15-ninja-win.zip"
powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-03-15-ninja-win.zip https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2017-03-15-ninja-win.zip"
7z x -oninja 2017-03-15-ninja-win.zip
del 2017-03-15-ninja-win.zip
set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --enable-ninja

View File

@ -199,7 +199,7 @@ steps:
# Upload CPU usage statistics that we've been gathering this whole time. Always
# execute this step in case we want to inspect failed builds, but don't let
# errors here ever fail the build since this is just informational.
- bash: aws s3 cp --acl public-read cpu-usage.csv s3://$DEPLOY_BUCKET/rustc-builds/$BUILD_SOURCEVERSION/cpu-$SYSTEM_JOBNAME.csv
- bash: aws s3 cp --acl public-read cpu-usage.csv s3://$DEPLOY_BUCKET/rustc-builds/$BUILD_SOURCEVERSION/cpu-$CI_JOB_NAME.csv
env:
AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY)
condition: variables['AWS_SECRET_ACCESS_KEY']

View File

@ -72,7 +72,7 @@ RUN arm-linux-gnueabihf-gcc addentropy.c -o rootfs/addentropy -static
# TODO: What is this?!
# Source of the file: https://github.com/vfdev-5/qemu-rpi2-vexpress/raw/master/vexpress-v2p-ca15-tc1.dtb
RUN curl -O https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/vexpress-v2p-ca15-tc1.dtb
RUN curl -O https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/vexpress-v2p-ca15-tc1.dtb
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh

View File

@ -5,7 +5,7 @@ mkdir /usr/local/mips-linux-musl
# originally from
# https://downloads.openwrt.org/snapshots/trunk/ar71xx/generic/
# OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2
URL="https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror"
URL="https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc"
FILE="OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2"
curl -L "$URL/$FILE" | tar xjf - -C /usr/local/mips-linux-musl --strip-components=2

View File

@ -5,7 +5,7 @@
set -ex
# Originally from https://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz
curl https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/clang%2Bllvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \
curl https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/clang%2Bllvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \
tar xJf -
export PATH=`pwd`/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04/bin:$PATH

View File

@ -4,7 +4,7 @@ set -ex
source shared.sh
VERSION=1.0.2k
URL=https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/openssl-$VERSION.tar.gz
URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/openssl-$VERSION.tar.gz
curl $URL | tar xzf -

View File

@ -25,7 +25,7 @@ cd netbsd
mkdir -p /x-tools/x86_64-unknown-netbsd/sysroot
URL=https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror
URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc
# Originally from ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-$BSD/source/sets/*.tgz
curl $URL/2018-03-01-netbsd-src.tgz | tar xzf -

View File

@ -23,8 +23,9 @@ REPOSITORIES = [
HOST_OS = "linux"
# Mirroring options
MIRROR_BUCKET = "rust-lang-ci2"
MIRROR_BASE_DIR = "rust-ci-mirror/android/"
MIRROR_BUCKET = "rust-lang-ci-mirrors"
MIRROR_BUCKET_REGION = "us-west-1"
MIRROR_BASE_DIR = "rustc/android/"
import argparse
import hashlib
@ -144,7 +145,8 @@ def cli_install(args):
lockfile = Lockfile(args.lockfile)
for package in lockfile.packages.values():
# Download the file from the mirror into a temp file
url = "https://" + MIRROR_BUCKET + ".s3.amazonaws.com/" + MIRROR_BASE_DIR
url = "https://" + MIRROR_BUCKET + ".s3-" + MIRROR_BUCKET_REGION + \
".amazonaws.com/" + MIRROR_BASE_DIR
downloaded = package.download(url)
# Extract the file in a temporary directory
extract_dir = tempfile.mkdtemp()

View File

@ -59,7 +59,7 @@ done
# Originally downloaded from:
# https://download.freebsd.org/ftp/releases/${freebsd_arch}/${freebsd_version}-RELEASE/base.txz
URL=https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2019-04-04-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz
URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2019-04-04-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz
curl "$URL" | tar xJf - -C "$sysroot" --wildcards "${files_to_extract[@]}"
# Fix up absolute symlinks from the system image. This can be removed

View File

@ -54,29 +54,3 @@ if [ "$REPLACE_CC" = "1" ]; then
ln -s $TARGET-g++ /usr/local/bin/$exec
done
fi
export CC=$TARGET-gcc
export CXX=$TARGET-g++
LLVM=70
# may have been downloaded in a previous run
if [ ! -d libunwind-release_$LLVM ]; then
curl -L https://github.com/llvm-mirror/llvm/archive/release_$LLVM.tar.gz | tar xzf -
curl -L https://github.com/llvm-mirror/libunwind/archive/release_$LLVM.tar.gz | tar xzf -
fi
# fixme(mati865): Replace it with https://github.com/rust-lang/rust/pull/59089
mkdir libunwind-build
cd libunwind-build
cmake ../libunwind-release_$LLVM \
-DLLVM_PATH=/build/llvm-release_$LLVM \
-DLIBUNWIND_ENABLE_SHARED=0 \
-DCMAKE_C_COMPILER=$CC \
-DCMAKE_CXX_COMPILER=$CXX \
-DCMAKE_C_FLAGS="$CFLAGS" \
-DCMAKE_CXX_FLAGS="$CXXFLAGS"
hide_output make -j$(nproc)
cp lib/libunwind.a $OUTPUT/$TARGET/lib
cd - && rm -rf libunwind-build

View File

@ -20,6 +20,8 @@ exit 1
TAG=$1
shift
# Ancient binutils versions don't understand debug symbols produced by more recent tools.
# Apparently applying `-fPIC` everywhere allows them to link successfully.
export CFLAGS="-fPIC $CFLAGS"
MUSL=musl-1.1.22
@ -38,27 +40,3 @@ else
fi
hide_output make install
hide_output make clean
cd ..
LLVM=70
# may have been downloaded in a previous run
if [ ! -d libunwind-release_$LLVM ]; then
curl -L https://github.com/llvm-mirror/llvm/archive/release_$LLVM.tar.gz | tar xzf -
curl -L https://github.com/llvm-mirror/libunwind/archive/release_$LLVM.tar.gz | tar xzf -
fi
mkdir libunwind-build
cd libunwind-build
cmake ../libunwind-release_$LLVM \
-DLLVM_PATH=/build/llvm-release_$LLVM \
-DLIBUNWIND_ENABLE_SHARED=0 \
-DCMAKE_C_COMPILER=$CC \
-DCMAKE_CXX_COMPILER=$CXX \
-DCMAKE_C_FLAGS="$CFLAGS" \
-DCMAKE_CXX_FLAGS="$CXXFLAGS"
hide_output make -j$(nproc)
cp lib/libunwind.a /musl-$TAG/lib
cd ../ && rm -rf libunwind-build

View File

@ -1,6 +1,6 @@
set -ex
curl -fo /usr/local/bin/sccache \
https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-02-sccache-x86_64-unknown-linux-musl
https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2018-04-02-sccache-x86_64-unknown-linux-musl
chmod +x /usr/local/bin/sccache

View File

@ -16,7 +16,7 @@
set -euo pipefail
IFS=$'\n\t'
MIRROR="https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2019-07-27-awscli.tar"
MIRROR="https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2019-07-27-awscli.tar"
DEPS_DIR="/tmp/awscli-deps"
pip="pip"

View File

@ -78,6 +78,21 @@ if [ "$RUST_RELEASE_CHANNEL" = "nightly" ] || [ "$DIST_REQUIRE_ALL_TOOLS" = "" ]
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-missing-tools"
fi
# Print the date from the local machine and the date from an external source to
# check for clock drifts. An HTTP URL is used instead of HTTPS since on Azure
# Pipelines it happened that the certificates were marked as expired.
datecheck() {
echo "== clock drift check =="
echo -n " local time: "
date
echo -n " network time: "
curl -fs --head http://detectportal.firefox.com/success.txt | grep ^Date: \
| sed 's/Date: //g' || true
echo "== end clock drift check =="
}
datecheck
trap datecheck EXIT
# We've had problems in the past of shell scripts leaking fds into the sccache
# server (#48192) which causes Cargo to erroneously think that a build script
# hasn't finished yet. Try to solve that problem by starting a very long-lived

View File

@ -1163,6 +1163,9 @@ impl<T> FusedIterator for Drain<'_, T> {}
#[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
impl<T: Ord> From<Vec<T>> for BinaryHeap<T> {
/// Converts a `Vec<T>` into a `BinaryHeap<T>`.
///
/// This conversion happens in-place, and has `O(n)` time complexity.
fn from(vec: Vec<T>) -> BinaryHeap<T> {
let mut heap = BinaryHeap { data: vec };
heap.rebuild();

View File

@ -106,8 +106,8 @@ impl<K, V> LeafNode<K, V> {
LeafNode {
// As a general policy, we leave fields uninitialized if they can be, as this should
// be both slightly faster and easier to track in Valgrind.
keys: uninit_array![_; CAPACITY],
vals: uninit_array![_; CAPACITY],
keys: [MaybeUninit::UNINIT; CAPACITY],
vals: [MaybeUninit::UNINIT; CAPACITY],
parent: ptr::null(),
parent_idx: MaybeUninit::uninit(),
len: 0
@ -159,7 +159,7 @@ impl<K, V> InternalNode<K, V> {
unsafe fn new() -> Self {
InternalNode {
data: LeafNode::new(),
edges: uninit_array![_; 2*B],
edges: [MaybeUninit::UNINIT; 2*B]
}
}
}

View File

@ -41,32 +41,35 @@ pub use linked_list::LinkedList;
#[doc(no_inline)]
pub use vec_deque::VecDeque;
use crate::alloc::{AllocErr, LayoutErr};
use crate::alloc::{Layout, LayoutErr};
/// Augments `AllocErr` with a CapacityOverflow variant.
/// The error type for `try_reserve` methods.
#[derive(Clone, PartialEq, Eq, Debug)]
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
pub enum CollectionAllocErr {
pub enum TryReserveError {
/// Error due to the computed capacity exceeding the collection's maximum
/// (usually `isize::MAX` bytes).
CapacityOverflow,
/// Error due to the allocator (see the `AllocErr` type's docs).
AllocErr,
/// The memory allocator returned an error
AllocError {
/// The layout of allocation request that failed
layout: Layout,
#[doc(hidden)]
#[unstable(feature = "container_error_extra", issue = "0", 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")]
non_exhaustive: (),
},
}
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
impl From<AllocErr> for CollectionAllocErr {
#[inline]
fn from(AllocErr: AllocErr) -> Self {
CollectionAllocErr::AllocErr
}
}
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
impl From<LayoutErr> for CollectionAllocErr {
impl From<LayoutErr> for TryReserveError {
#[inline]
fn from(_: LayoutErr) -> Self {
CollectionAllocErr::CapacityOverflow
TryReserveError::CapacityOverflow
}
}

View File

@ -18,7 +18,7 @@ use core::ptr::{self, NonNull};
use core::slice;
use core::hash::{Hash, Hasher};
use crate::collections::CollectionAllocErr;
use crate::collections::TryReserveError;
use crate::raw_vec::RawVec;
use crate::vec::Vec;
@ -576,10 +576,10 @@ impl<T> VecDeque<T> {
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::CollectionAllocErr;
/// use std::collections::TryReserveError;
/// use std::collections::VecDeque;
///
/// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, CollectionAllocErr> {
/// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, TryReserveError> {
/// let mut output = VecDeque::new();
///
/// // Pre-reserve the memory, exiting if we can't
@ -595,7 +595,7 @@ 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<(), CollectionAllocErr> {
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.try_reserve(additional)
}
@ -614,10 +614,10 @@ impl<T> VecDeque<T> {
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::CollectionAllocErr;
/// use std::collections::TryReserveError;
/// use std::collections::VecDeque;
///
/// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, CollectionAllocErr> {
/// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, TryReserveError> {
/// let mut output = VecDeque::new();
///
/// // Pre-reserve the memory, exiting if we can't
@ -633,12 +633,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")]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
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)
.and_then(|needed_cap| needed_cap.checked_next_power_of_two())
.ok_or(CollectionAllocErr::CapacityOverflow)?;
.ok_or(TryReserveError::CapacityOverflow)?;
if new_cap > old_cap {
self.buf.try_reserve_exact(used_cap, new_cap - used_cap)?;

View File

@ -69,7 +69,7 @@
#![warn(missing_debug_implementations)]
#![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings
#![allow(explicit_outlives_requirements)]
#![cfg_attr(not(bootstrap), allow(incomplete_features))]
#![allow(incomplete_features)]
#![cfg_attr(not(test), feature(generator_trait))]
#![cfg_attr(test, feature(test))]
@ -84,9 +84,10 @@
#![feature(coerce_unsized)]
#![feature(const_generic_impls_guard)]
#![feature(const_generics)]
#![cfg_attr(not(bootstrap), feature(const_in_array_repeat_expressions))]
#![feature(const_in_array_repeat_expressions)]
#![feature(dispatch_from_dyn)]
#![feature(core_intrinsics)]
#![feature(container_error_extra)]
#![feature(dropck_eyepatch)]
#![feature(exact_size_is_empty)]
#![feature(fmt_internals)]
@ -118,7 +119,7 @@
#![feature(rustc_const_unstable)]
#![feature(const_vec_new)]
#![feature(slice_partition_dedup)]
#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)]
#![feature(maybe_uninit_extra, maybe_uninit_slice)]
#![feature(alloc_layout_extra)]
#![feature(try_trait)]
#![feature(mem_take)]

View File

@ -98,5 +98,5 @@ macro_rules! vec {
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! format {
($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*)))
($($arg:tt)*) => ($crate::fmt::format(::core::format_args!($($arg)*)))
}

View File

@ -7,8 +7,8 @@ use core::ops::Drop;
use core::ptr::{self, NonNull, Unique};
use core::slice;
use crate::alloc::{Alloc, Layout, Global, handle_alloc_error};
use crate::collections::CollectionAllocErr::{self, *};
use crate::alloc::{Alloc, Layout, Global, AllocErr, handle_alloc_error};
use crate::collections::TryReserveError::{self, *};
use crate::boxed::Box;
#[cfg(test)]
@ -385,7 +385,7 @@ impl<T, A: Alloc> RawVec<T, A> {
/// 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<(), CollectionAllocErr> {
-> Result<(), TryReserveError> {
self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Exact)
}
@ -413,7 +413,7 @@ impl<T, A: Alloc> RawVec<T, A> {
pub fn reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) {
match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Exact) {
Err(CapacityOverflow) => capacity_overflow(),
Err(AllocErr) => unreachable!(),
Err(AllocError { .. }) => unreachable!(),
Ok(()) => { /* yay */ }
}
}
@ -422,7 +422,7 @@ impl<T, A: Alloc> RawVec<T, A> {
/// 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, CollectionAllocErr> {
-> Result<usize, TryReserveError> {
// Nothing we can really do about these checks :(
let required_cap = used_capacity.checked_add(needed_extra_capacity)
@ -435,7 +435,7 @@ 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<(), CollectionAllocErr> {
-> Result<(), TryReserveError> {
self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Amortized)
}
@ -494,7 +494,7 @@ impl<T, A: Alloc> RawVec<T, A> {
pub fn reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) {
match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Amortized) {
Err(CapacityOverflow) => capacity_overflow(),
Err(AllocErr) => unreachable!(),
Err(AllocError { .. }) => unreachable!(),
Ok(()) => { /* yay */ }
}
}
@ -640,10 +640,8 @@ impl<T, A: Alloc> RawVec<T, A> {
needed_extra_capacity: usize,
fallibility: Fallibility,
strategy: ReserveStrategy,
) -> Result<(), CollectionAllocErr> {
) -> Result<(), TryReserveError> {
unsafe {
use crate::alloc::AllocErr;
// NOTE: we don't early branch on ZSTs here because we want this
// to actually catch "asking for more than usize::MAX" in that case.
// If we make it past the first branch then we are guaranteed to
@ -672,12 +670,16 @@ impl<T, A: Alloc> RawVec<T, A> {
None => self.a.alloc(new_layout),
};
match (&res, fallibility) {
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: (),
}),
(Ok(ptr), _) => ptr,
};
self.ptr = res?.cast().into();
self.ptr = ptr.cast().into();
self.cap = new_cap;
Ok(())
@ -737,7 +739,7 @@ unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec<T, A> {
// all 4GB in user-space. e.g., PAE or x32
#[inline]
fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> {
fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> {
if mem::size_of::<usize>() < 8 && alloc_size > core::isize::MAX as usize {
Err(CapacityOverflow)
} else {

View File

@ -56,7 +56,7 @@ use core::ptr;
use core::str::{pattern::Pattern, lossy};
use crate::borrow::{Cow, ToOwned};
use crate::collections::CollectionAllocErr;
use crate::collections::TryReserveError;
use crate::boxed::Box;
use crate::str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars};
use crate::vec::Vec;
@ -937,9 +937,9 @@ impl String {
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::CollectionAllocErr;
/// use std::collections::TryReserveError;
///
/// fn process_data(data: &str) -> Result<String, CollectionAllocErr> {
/// fn process_data(data: &str) -> Result<String, TryReserveError> {
/// let mut output = String::new();
///
/// // Pre-reserve the memory, exiting if we can't
@ -953,7 +953,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")]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.vec.try_reserve(additional)
}
@ -975,9 +975,9 @@ impl String {
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::CollectionAllocErr;
/// use std::collections::TryReserveError;
///
/// fn process_data(data: &str) -> Result<String, CollectionAllocErr> {
/// fn process_data(data: &str) -> Result<String, TryReserveError> {
/// let mut output = String::new();
///
/// // Pre-reserve the memory, exiting if we can't
@ -991,7 +991,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")]
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.vec.try_reserve_exact(additional)
}

View File

@ -1,5 +1,5 @@
use std::borrow::Cow;
use std::collections::CollectionAllocErr::*;
use std::collections::TryReserveError::*;
use std::mem::size_of;
use std::{usize, isize};
@ -566,11 +566,11 @@ fn test_try_reserve() {
} else { panic!("usize::MAX should trigger an overflow!") }
} else {
// Check isize::MAX + 1 is an OOM
if let Err(AllocErr) = empty_string.try_reserve(MAX_CAP + 1) {
if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_CAP + 1) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
// Check usize::MAX is an OOM
if let Err(AllocErr) = empty_string.try_reserve(MAX_USIZE) {
if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_USIZE) {
} else { panic!("usize::MAX should trigger an OOM!") }
}
}
@ -590,7 +590,7 @@ fn test_try_reserve() {
if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an overflow!"); }
} else {
if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) {
if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
}
// Should always overflow in the add-to-len
@ -629,10 +629,10 @@ fn test_try_reserve_exact() {
if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_USIZE) {
} else { panic!("usize::MAX should trigger an overflow!") }
} else {
if let Err(AllocErr) = empty_string.try_reserve_exact(MAX_CAP + 1) {
if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_CAP + 1) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
if let Err(AllocErr) = empty_string.try_reserve_exact(MAX_USIZE) {
if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_USIZE) {
} else { panic!("usize::MAX should trigger an OOM!") }
}
}
@ -651,7 +651,7 @@ fn test_try_reserve_exact() {
if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an overflow!"); }
} else {
if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
}
if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {

View File

@ -2,7 +2,7 @@ use std::borrow::Cow;
use std::mem::size_of;
use std::{usize, isize};
use std::vec::{Drain, IntoIter};
use std::collections::CollectionAllocErr::*;
use std::collections::TryReserveError::*;
struct DropCounter<'a> {
count: &'a mut u32,
@ -1121,11 +1121,11 @@ fn test_try_reserve() {
} else { panic!("usize::MAX should trigger an overflow!") }
} else {
// Check isize::MAX + 1 is an OOM
if let Err(AllocErr) = empty_bytes.try_reserve(MAX_CAP + 1) {
if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP + 1) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
// Check usize::MAX is an OOM
if let Err(AllocErr) = empty_bytes.try_reserve(MAX_USIZE) {
if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE) {
} else { panic!("usize::MAX should trigger an OOM!") }
}
}
@ -1145,7 +1145,7 @@ fn test_try_reserve() {
if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an overflow!"); }
} else {
if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) {
if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
}
// Should always overflow in the add-to-len
@ -1168,7 +1168,7 @@ fn test_try_reserve() {
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(AllocErr) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
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
@ -1209,10 +1209,10 @@ fn test_try_reserve_exact() {
if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) {
} else { panic!("usize::MAX should trigger an overflow!") }
} else {
if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_CAP + 1) {
if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP + 1) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_USIZE) {
if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_USIZE) {
} else { panic!("usize::MAX should trigger an OOM!") }
}
}
@ -1231,7 +1231,7 @@ fn test_try_reserve_exact() {
if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an overflow!"); }
} else {
if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
}
if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
@ -1252,7 +1252,7 @@ fn test_try_reserve_exact() {
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(AllocErr) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
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) {

View File

@ -1,6 +1,6 @@
use std::fmt::Debug;
use std::collections::{VecDeque, vec_deque::Drain};
use std::collections::CollectionAllocErr::*;
use std::collections::TryReserveError::*;
use std::mem::size_of;
use std::{usize, isize};
@ -1168,7 +1168,7 @@ fn test_try_reserve() {
// VecDeque starts with capacity 7, always adds 1 to the capacity
// and also rounds the number to next power of 2 so this is the
// furthest we can go without triggering CapacityOverflow
if let Err(AllocErr) = empty_bytes.try_reserve(MAX_CAP) {
if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
}
}
@ -1188,7 +1188,7 @@ fn test_try_reserve() {
if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an overflow!"); }
} else {
if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) {
if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
}
// Should always overflow in the add-to-len
@ -1211,7 +1211,7 @@ fn test_try_reserve() {
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(AllocErr) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
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
@ -1256,7 +1256,7 @@ fn test_try_reserve_exact() {
// VecDeque starts with capacity 7, always adds 1 to the capacity
// and also rounds the number to next power of 2 so this is the
// furthest we can go without triggering CapacityOverflow
if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_CAP) {
if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
}
}
@ -1275,7 +1275,7 @@ fn test_try_reserve_exact() {
if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an overflow!"); }
} else {
if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
}
if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
@ -1296,7 +1296,7 @@ fn test_try_reserve_exact() {
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(AllocErr) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
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) {

View File

@ -70,7 +70,7 @@ use core::ptr::{self, NonNull};
use core::slice::{self, SliceIndex};
use crate::borrow::{ToOwned, Cow};
use crate::collections::CollectionAllocErr;
use crate::collections::TryReserveError;
use crate::boxed::Box;
use crate::raw_vec::RawVec;
@ -498,9 +498,9 @@ impl<T> Vec<T> {
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::CollectionAllocErr;
/// use std::collections::TryReserveError;
///
/// fn process_data(data: &[u32]) -> Result<Vec<u32>, CollectionAllocErr> {
/// fn process_data(data: &[u32]) -> Result<Vec<u32>, TryReserveError> {
/// let mut output = Vec::new();
///
/// // Pre-reserve the memory, exiting if we can't
@ -516,7 +516,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")]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.buf.try_reserve(self.len, additional)
}
@ -538,9 +538,9 @@ impl<T> Vec<T> {
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::CollectionAllocErr;
/// use std::collections::TryReserveError;
///
/// fn process_data(data: &[u32]) -> Result<Vec<u32>, CollectionAllocErr> {
/// fn process_data(data: &[u32]) -> Result<Vec<u32>, TryReserveError> {
/// let mut output = Vec::new();
///
/// // Pre-reserve the memory, exiting if we can't
@ -556,7 +556,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")]
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.buf.try_reserve_exact(self.len, additional)
}

View File

@ -470,10 +470,5 @@ impl TypeId {
#[stable(feature = "type_name", since = "1.38.0")]
#[rustc_const_unstable(feature = "const_type_name")]
pub const fn type_name<T: ?Sized>() -> &'static str {
#[cfg(bootstrap)]
unsafe {
intrinsics::type_name::<T>()
}
#[cfg(not(bootstrap))]
intrinsics::type_name::<T>()
}

View File

@ -14,6 +14,7 @@
use crate::fmt;
use crate::ops::Range;
use crate::iter::FusedIterator;
use crate::str::from_utf8_unchecked;
/// An iterator over the escaped version of a byte.
///
@ -22,6 +23,7 @@ use crate::iter::FusedIterator;
///
/// [`escape_default`]: fn.escape_default.html
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct EscapeDefault {
range: Range<usize>,
data: [u8; 4],
@ -130,6 +132,13 @@ impl ExactSizeIterator for EscapeDefault {}
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for EscapeDefault {}
#[stable(feature = "ascii_escape_display", since = "1.39.0")]
impl fmt::Display for EscapeDefault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) })
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for EscapeDefault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

View File

@ -553,12 +553,7 @@ impl char {
/// `XID_Start` is a Unicode Derived Property specified in
/// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
/// mostly similar to `ID_Start` but modified for closure under `NFKx`.
#[cfg_attr(bootstrap,
unstable(feature = "rustc_private",
reason = "mainly needed for compiler internals",
issue = "27812"))]
#[cfg_attr(not(bootstrap),
unstable(feature = "unicode_internals", issue = "0"))]
#[unstable(feature = "unicode_internals", issue = "0")]
pub fn is_xid_start(self) -> bool {
derived_property::XID_Start(self)
}
@ -569,12 +564,7 @@ impl char {
/// `XID_Continue` is a Unicode Derived Property specified in
/// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
/// mostly similar to `ID_Continue` but modified for closure under NFKx.
#[cfg_attr(bootstrap,
unstable(feature = "rustc_private",
reason = "mainly needed for compiler internals",
issue = "27812"))]
#[cfg_attr(not(bootstrap),
unstable(feature = "unicode_internals", issue = "0"))]
#[unstable(feature = "unicode_internals", issue = "0")]
#[inline]
pub fn is_xid_continue(self) -> bool {
derived_property::XID_Continue(self)

View File

@ -134,9 +134,8 @@ pub trait Clone : Sized {
}
/// Derive macro generating an impl of the trait `Clone`.
#[cfg(not(bootstrap))]
#[rustc_builtin_macro]
#[rustc_macro_transparency = "semitransparent"]
#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics, derive_clone_copy)]
pub macro Clone($item:item) { /* compiler built-in */ }

View File

@ -201,9 +201,8 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
}
/// Derive macro generating an impl of the trait `PartialEq`.
#[cfg(not(bootstrap))]
#[rustc_builtin_macro]
#[rustc_macro_transparency = "semitransparent"]
#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics)]
pub macro PartialEq($item:item) { /* compiler built-in */ }
@ -265,9 +264,8 @@ pub trait Eq: PartialEq<Self> {
}
/// Derive macro generating an impl of the trait `Eq`.
#[cfg(not(bootstrap))]
#[rustc_builtin_macro]
#[rustc_macro_transparency = "semitransparent"]
#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics, derive_eq)]
pub macro Eq($item:item) { /* compiler built-in */ }
@ -617,9 +615,8 @@ pub trait Ord: Eq + PartialOrd<Self> {
}
/// Derive macro generating an impl of the trait `Ord`.
#[cfg(not(bootstrap))]
#[rustc_builtin_macro]
#[rustc_macro_transparency = "semitransparent"]
#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics)]
pub macro Ord($item:item) { /* compiler built-in */ }
@ -867,9 +864,8 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
}
/// Derive macro generating an impl of the trait `PartialOrd`.
#[cfg(not(bootstrap))]
#[rustc_builtin_macro]
#[rustc_macro_transparency = "semitransparent"]
#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics)]
pub macro PartialOrd($item:item) { /* compiler built-in */ }

View File

@ -116,9 +116,8 @@ pub trait Default: Sized {
}
/// Derive macro generating an impl of the trait `Default`.
#[cfg(not(bootstrap))]
#[rustc_builtin_macro]
#[rustc_macro_transparency = "semitransparent"]
#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics)]
pub macro Default($item:item) { /* compiler built-in */ }

View File

@ -98,7 +98,7 @@ pub struct DebugStruct<'a, 'b: 'a> {
has_fields: bool,
}
pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'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);
@ -251,7 +251,10 @@ pub struct DebugTuple<'a, 'b: 'a> {
empty_name: bool,
}
pub fn debug_tuple_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugTuple<'a, 'b> {
pub(super) fn debug_tuple_new<'a, 'b>(
fmt: &'a mut fmt::Formatter<'b>,
name: &str,
) -> DebugTuple<'a, 'b> {
let result = fmt.write_str(name);
DebugTuple {
fmt,
@ -418,7 +421,7 @@ pub struct DebugSet<'a, 'b: 'a> {
inner: DebugInner<'a, 'b>,
}
pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> {
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 {
@ -555,7 +558,7 @@ pub struct DebugList<'a, 'b: 'a> {
inner: DebugInner<'a, 'b>,
}
pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> {
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 {
@ -697,7 +700,7 @@ pub struct DebugMap<'a, 'b: 'a> {
state: PadAdapterState,
}
pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
pub(super) fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
let result = fmt.write_str("{");
DebugMap {
fmt,

View File

@ -546,16 +546,14 @@ pub trait Debug {
}
// Separate module to reexport the macro `Debug` from prelude without the trait `Debug`.
#[cfg(not(bootstrap))]
pub(crate) mod macros {
/// Derive macro generating an impl of the trait `Debug`.
#[rustc_builtin_macro]
#[rustc_macro_transparency = "semitransparent"]
#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics)]
pub macro Debug($item:item) { /* compiler built-in */ }
}
#[cfg(not(bootstrap))]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[doc(inline)]
pub use macros::Debug;

View File

@ -199,16 +199,14 @@ pub trait Hash {
}
// Separate module to reexport the macro `Hash` from prelude without the trait `Hash`.
#[cfg(not(bootstrap))]
pub(crate) mod macros {
/// Derive macro generating an impl of the trait `Hash`.
#[rustc_builtin_macro]
#[rustc_macro_transparency = "semitransparent"]
#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics)]
pub macro Hash($item:item) { /* compiler built-in */ }
}
#[cfg(not(bootstrap))]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[doc(inline)]
pub use macros::Hash;
@ -553,8 +551,6 @@ impl<H> PartialEq for BuildHasherDefault<H> {
#[stable(since = "1.29.0", feature = "build_hasher_eq")]
impl<H> Eq for BuildHasherDefault<H> {}
//////////////////////////////////////////////////////////////////////////////
mod impls {
use crate::mem;
use crate::slice;

View File

@ -1293,18 +1293,40 @@ extern "rust-intrinsic" {
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `wrapping_add` method. For example,
/// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add)
#[cfg(boostrap_stdarch_ignore_this)]
pub fn overflowing_add<T>(a: T, b: T) -> T;
/// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `wrapping_sub` method. For example,
/// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub)
#[cfg(boostrap_stdarch_ignore_this)]
pub fn overflowing_sub<T>(a: T, b: T) -> T;
/// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `wrapping_mul` method. For example,
/// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul)
#[cfg(boostrap_stdarch_ignore_this)]
pub fn overflowing_mul<T>(a: T, b: T) -> T;
/// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `wrapping_add` method. For example,
/// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add)
#[cfg(not(boostrap_stdarch_ignore_this))]
pub fn wrapping_add<T>(a: T, b: T) -> T;
/// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `wrapping_sub` method. For example,
/// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub)
#[cfg(not(boostrap_stdarch_ignore_this))]
pub fn wrapping_sub<T>(a: T, b: T) -> T;
/// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `wrapping_mul` method. For example,
/// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul)
#[cfg(not(boostrap_stdarch_ignore_this))]
pub fn wrapping_mul<T>(a: T, b: T) -> T;
/// Computes `a + b`, while saturating at numeric bounds.
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `saturating_add` method. For example,

View File

@ -207,6 +207,29 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where
}
}
#[inline]
fn nth_back(&mut self, mut n: usize) -> Option<A::Item> {
match self.state {
ChainState::Both | ChainState::Back => {
for x in self.b.by_ref().rev() {
if n == 0 {
return Some(x)
}
n -= 1;
}
if let ChainState::Both = self.state {
self.state = ChainState::Front;
}
}
ChainState::Front => {}
}
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>
{

View File

@ -72,8 +72,7 @@ impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F>
where
F: FnMut(I::Item) -> U,
U: IntoIterator,
U::IntoIter: DoubleEndedIterator,
U: IntoIterator<IntoIter: DoubleEndedIterator>,
{
#[inline]
fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() }
@ -107,10 +106,7 @@ impl<I, U, F> FusedIterator for FlatMap<I, U, F>
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "iterator_flatten", since = "1.29.0")]
pub struct Flatten<I: Iterator>
where
I::Item: IntoIterator,
{
pub struct Flatten<I: Iterator<Item: IntoIterator>> {
inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
}
@ -229,7 +225,7 @@ where
if let elt@Some(_) = inner.next() { return elt }
}
match self.iter.next() {
None => return self.backiter.as_mut().and_then(|it| it.next()),
None => return self.backiter.as_mut()?.next(),
Some(inner) => self.frontiter = Some(inner.into_iter()),
}
}
@ -237,8 +233,8 @@ where
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), |it| it.size_hint());
let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), |it| it.size_hint());
let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint);
let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint);
let lo = flo.saturating_add(blo);
match (self.iter.size_hint(), fhi, bhi) {
((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
@ -250,20 +246,25 @@ where
fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
#[inline]
fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
frontiter: &'a mut Option<T::IntoIter>,
fold: &'a mut impl FnMut(Acc, T::Item) -> R,
) -> impl FnMut(Acc, T) -> R + 'a {
move |acc, x| {
let mut mid = x.into_iter();
let r = mid.try_fold(acc, &mut *fold);
*frontiter = Some(mid);
r
}
}
if let Some(ref mut front) = self.frontiter {
init = front.try_fold(init, &mut fold)?;
}
self.frontiter = None;
{
let frontiter = &mut self.frontiter;
init = self.iter.try_fold(init, |acc, x| {
let mut mid = x.into_iter();
let r = mid.try_fold(acc, &mut fold);
*frontiter = Some(mid);
r
})?;
}
init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?;
self.frontiter = None;
if let Some(ref mut back) = self.backiter {
@ -275,13 +276,20 @@ where
}
#[inline]
fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
fn fold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
where Fold: FnMut(Acc, Self::Item) -> Acc,
{
#[inline]
fn flatten<U: Iterator, Acc>(
fold: &mut impl FnMut(Acc, U::Item) -> Acc,
) -> impl FnMut(Acc, U) -> Acc + '_ {
move |acc, iter| iter.fold(acc, &mut *fold)
}
self.frontiter.into_iter()
.chain(self.iter.map(IntoIterator::into_iter))
.chain(self.backiter)
.fold(init, |acc, iter| iter.fold(acc, &mut fold))
.fold(init, flatten(fold))
}
}
@ -297,7 +305,7 @@ where
if let elt@Some(_) = inner.next_back() { return elt }
}
match self.iter.next_back() {
None => return self.frontiter.as_mut().and_then(|it| it.next_back()),
None => return self.frontiter.as_mut()?.next_back(),
next => self.backiter = next.map(IntoIterator::into_iter),
}
}
@ -307,20 +315,27 @@ where
fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
#[inline]
fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
backiter: &'a mut Option<T::IntoIter>,
fold: &'a mut impl FnMut(Acc, T::Item) -> R,
) -> impl FnMut(Acc, T) -> R + 'a where
T::IntoIter: DoubleEndedIterator,
{
move |acc, x| {
let mut mid = x.into_iter();
let r = mid.try_rfold(acc, &mut *fold);
*backiter = Some(mid);
r
}
}
if let Some(ref mut back) = self.backiter {
init = back.try_rfold(init, &mut fold)?;
}
self.backiter = None;
{
let backiter = &mut self.backiter;
init = self.iter.try_rfold(init, |acc, x| {
let mut mid = x.into_iter();
let r = mid.try_rfold(acc, &mut fold);
*backiter = Some(mid);
r
})?;
}
init = self.iter.try_rfold(init, flatten(&mut self.backiter, &mut fold))?;
self.backiter = None;
if let Some(ref mut front) = self.frontiter {
@ -332,12 +347,19 @@ where
}
#[inline]
fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
fn rfold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
where Fold: FnMut(Acc, Self::Item) -> Acc,
{
#[inline]
fn flatten<U: DoubleEndedIterator, Acc>(
fold: &mut impl FnMut(Acc, U::Item) -> Acc,
) -> impl FnMut(Acc, U) -> Acc + '_ {
move |acc, iter| iter.rfold(acc, &mut *fold)
}
self.frontiter.into_iter()
.chain(self.iter.map(IntoIterator::into_iter))
.chain(self.backiter)
.rfold(init, |acc, iter| iter.rfold(acc, &mut fold))
.rfold(init, flatten(fold))
}
}

View File

@ -1,6 +1,6 @@
use crate::cmp;
use crate::fmt;
use crate::ops::Try;
use crate::ops::{Add, AddAssign, Try};
use crate::usize;
use crate::intrinsics;
@ -143,6 +143,18 @@ impl<I> Copied<I> {
}
}
fn copy_fold<T: Copy, Acc>(
mut f: impl FnMut(Acc, T) -> Acc,
) -> impl FnMut(Acc, &T) -> Acc {
move |acc, &elt| f(acc, elt)
}
fn copy_try_fold<T: Copy, Acc, R>(
mut f: impl FnMut(Acc, T) -> R,
) -> impl FnMut(Acc, &T) -> R {
move |acc, &elt| f(acc, elt)
}
#[stable(feature = "iter_copied", since = "1.36.0")]
impl<'a, I, T: 'a> Iterator for Copied<I>
where I: Iterator<Item=&'a T>, T: Copy
@ -157,16 +169,16 @@ impl<'a, I, T: 'a> Iterator for Copied<I>
self.it.size_hint()
}
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where
Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
{
self.it.try_fold(init, move |acc, &elt| f(acc, elt))
self.it.try_fold(init, copy_try_fold(f))
}
fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
where F: FnMut(Acc, Self::Item) -> Acc,
{
self.it.fold(init, move |acc, &elt| f(acc, elt))
self.it.fold(init, copy_fold(f))
}
}
@ -178,16 +190,16 @@ impl<'a, I, T: 'a> DoubleEndedIterator for Copied<I>
self.it.next_back().copied()
}
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R where
Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
{
self.it.try_rfold(init, move |acc, &elt| f(acc, elt))
self.it.try_rfold(init, copy_try_fold(f))
}
fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc
fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
where F: FnMut(Acc, Self::Item) -> Acc,
{
self.it.rfold(init, move |acc, &elt| f(acc, elt))
self.it.rfold(init, copy_fold(f))
}
}
@ -248,6 +260,12 @@ impl<I> Cloned<I> {
}
}
fn clone_try_fold<T: Clone, Acc, R>(
mut f: impl FnMut(Acc, T) -> R,
) -> impl FnMut(Acc, &T) -> R {
move |acc, elt| f(acc, elt.clone())
}
#[stable(feature = "iter_cloned", since = "1.1.0")]
impl<'a, I, T: 'a> Iterator for Cloned<I>
where I: Iterator<Item=&'a T>, T: Clone
@ -262,16 +280,16 @@ impl<'a, I, T: 'a> Iterator for Cloned<I>
self.it.size_hint()
}
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where
Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
{
self.it.try_fold(init, move |acc, elt| f(acc, elt.clone()))
self.it.try_fold(init, clone_try_fold(f))
}
fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
where F: FnMut(Acc, Self::Item) -> Acc,
{
self.it.fold(init, move |acc, elt| f(acc, elt.clone()))
self.it.map(T::clone).fold(init, f)
}
}
@ -283,16 +301,16 @@ impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I>
self.it.next_back().cloned()
}
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R where
Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
{
self.it.try_rfold(init, move |acc, elt| f(acc, elt.clone()))
self.it.try_rfold(init, clone_try_fold(f))
}
fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc
fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
where F: FnMut(Acc, Self::Item) -> Acc,
{
self.it.rfold(init, move |acc, elt| f(acc, elt.clone()))
self.it.map(T::clone).rfold(init, f)
}
}
@ -387,6 +405,36 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator {
_ => (usize::MAX, None)
}
}
#[inline]
fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
where
F: FnMut(Acc, Self::Item) -> R,
R: Try<Ok = Acc>,
{
// fully iterate the current iterator. this is necessary because
// `self.iter` may be empty even when `self.orig` isn't
acc = self.iter.try_fold(acc, &mut f)?;
self.iter = self.orig.clone();
// complete a full cycle, keeping track of whether the cycled
// iterator is empty or not. we need to return early in case
// of an empty iterator to prevent an infinite loop
let mut is_empty = true;
acc = self.iter.try_fold(acc, |acc, x| {
is_empty = false;
f(acc, x)
})?;
if is_empty {
return Try::from_ok(acc);
}
loop {
self.iter = self.orig.clone();
acc = self.iter.try_fold(acc, &mut f)?;
}
}
}
#[stable(feature = "fused", since = "1.26.0")]
@ -430,14 +478,24 @@ impl<I> Iterator for StepBy<I> where I: Iterator {
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let inner_hint = self.iter.size_hint();
#[inline]
fn first_size(step: usize) -> impl Fn(usize) -> usize {
move |n| if n == 0 { 0 } else { 1 + (n - 1) / (step + 1) }
}
#[inline]
fn other_size(step: usize) -> impl Fn(usize) -> usize {
move |n| n / (step + 1)
}
let (low, high) = self.iter.size_hint();
if self.first_take {
let f = |n| if n == 0 { 0 } else { 1 + (n-1)/(self.step+1) };
(f(inner_hint.0), inner_hint.1.map(f))
let f = first_size(self.step);
(f(low), high.map(f))
} else {
let f = |n| n / (self.step+1);
(f(inner_hint.0), inner_hint.1.map(f))
let f = other_size(self.step);
(f(low), high.map(f))
}
}
@ -594,6 +652,20 @@ impl<I: fmt::Debug, F> fmt::Debug for Map<I, F> {
}
}
fn map_fold<T, B, Acc>(
mut f: impl FnMut(T) -> B,
mut g: impl FnMut(Acc, B) -> Acc,
) -> impl FnMut(Acc, T) -> Acc {
move |acc, elt| g(acc, f(elt))
}
fn map_try_fold<'a, T, B, Acc, R>(
f: &'a mut impl FnMut(T) -> B,
mut g: impl FnMut(Acc, B) -> R + 'a,
) -> impl FnMut(Acc, T) -> R + 'a {
move |acc, elt| g(acc, f(elt))
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B {
type Item = B;
@ -608,18 +680,16 @@ impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B {
self.iter.size_hint()
}
fn try_fold<Acc, G, R>(&mut self, init: Acc, mut g: G) -> R where
fn try_fold<Acc, G, R>(&mut self, init: Acc, g: G) -> R where
Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
let f = &mut self.f;
self.iter.try_fold(init, move |acc, elt| g(acc, f(elt)))
self.iter.try_fold(init, map_try_fold(&mut self.f, g))
}
fn fold<Acc, G>(self, init: Acc, mut g: G) -> Acc
fn fold<Acc, G>(self, init: Acc, g: G) -> Acc
where G: FnMut(Acc, Self::Item) -> Acc,
{
let mut f = self.f;
self.iter.fold(init, move |acc, elt| g(acc, f(elt)))
self.iter.fold(init, map_fold(self.f, g))
}
}
@ -632,18 +702,16 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F> where
self.iter.next_back().map(&mut self.f)
}
fn try_rfold<Acc, G, R>(&mut self, init: Acc, mut g: G) -> R where
fn try_rfold<Acc, G, R>(&mut self, init: Acc, g: G) -> R where
Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
let f = &mut self.f;
self.iter.try_rfold(init, move |acc, elt| g(acc, f(elt)))
self.iter.try_rfold(init, map_try_fold(&mut self.f, g))
}
fn rfold<Acc, G>(self, init: Acc, mut g: G) -> Acc
fn rfold<Acc, G>(self, init: Acc, g: G) -> Acc
where G: FnMut(Acc, Self::Item) -> Acc,
{
let mut f = self.f;
self.iter.rfold(init, move |acc, elt| g(acc, f(elt)))
self.iter.rfold(init, map_fold(self.f, g))
}
}
@ -710,13 +778,27 @@ impl<I: fmt::Debug, P> fmt::Debug for Filter<I, P> {
}
}
fn filter_fold<T, Acc>(
mut predicate: impl FnMut(&T) -> bool,
mut fold: impl FnMut(Acc, T) -> Acc,
) -> impl FnMut(Acc, T) -> Acc {
move |acc, item| if predicate(&item) { fold(acc, item) } else { acc }
}
fn filter_try_fold<'a, T, Acc, R: Try<Ok = Acc>>(
predicate: &'a mut impl FnMut(&T) -> bool,
mut fold: impl FnMut(Acc, T) -> R + 'a,
) -> impl FnMut(Acc, T) -> R + 'a {
move |acc, item| if predicate(&item) { fold(acc, item) } else { R::from_ok(acc) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool {
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<I::Item> {
self.try_for_each(Err).err()
self.iter.find(&mut self.predicate)
}
#[inline]
@ -738,32 +820,26 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool
// leaving more budget for LLVM optimizations.
#[inline]
fn count(self) -> usize {
let mut predicate = self.predicate;
self.iter.map(|x| predicate(&x) as usize).sum()
#[inline]
fn to_usize<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> usize {
move |x| predicate(&x) as usize
}
self.iter.map(to_usize(self.predicate)).sum()
}
#[inline]
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
let predicate = &mut self.predicate;
self.iter.try_fold(init, move |acc, item| if predicate(&item) {
fold(acc, item)
} else {
Try::from_ok(acc)
})
self.iter.try_fold(init, filter_try_fold(&mut self.predicate, fold))
}
#[inline]
fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
where Fold: FnMut(Acc, Self::Item) -> Acc,
{
let mut predicate = self.predicate;
self.iter.fold(init, move |acc, item| if predicate(&item) {
fold(acc, item)
} else {
acc
})
self.iter.fold(init, filter_fold(self.predicate, fold))
}
}
@ -773,31 +849,21 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P>
{
#[inline]
fn next_back(&mut self) -> Option<I::Item> {
self.try_rfold((), |_, x| Err(x)).err()
self.iter.rfind(&mut self.predicate)
}
#[inline]
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
let predicate = &mut self.predicate;
self.iter.try_rfold(init, move |acc, item| if predicate(&item) {
fold(acc, item)
} else {
Try::from_ok(acc)
})
self.iter.try_rfold(init, filter_try_fold(&mut self.predicate, fold))
}
#[inline]
fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
where Fold: FnMut(Acc, Self::Item) -> Acc,
{
let mut predicate = self.predicate;
self.iter.rfold(init, move |acc, item| if predicate(&item) {
fold(acc, item)
} else {
acc
})
self.iter.rfold(init, filter_fold(self.predicate, fold))
}
}
@ -834,6 +900,26 @@ impl<I: fmt::Debug, F> fmt::Debug for FilterMap<I, F> {
}
}
fn filter_map_fold<T, B, Acc>(
mut f: impl FnMut(T) -> Option<B>,
mut fold: impl FnMut(Acc, B) -> Acc,
) -> impl FnMut(Acc, T) -> Acc {
move |acc, item| match f(item) {
Some(x) => fold(acc, x),
None => acc,
}
}
fn filter_map_try_fold<'a, T, B, Acc, R: Try<Ok = Acc>>(
f: &'a mut impl FnMut(T) -> Option<B>,
mut fold: impl FnMut(Acc, B) -> R + 'a,
) -> impl FnMut(Acc, T) -> R + 'a {
move |acc, item| match f(item) {
Some(x) => fold(acc, x),
None => R::from_ok(acc),
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
where F: FnMut(I::Item) -> Option<B>,
@ -842,7 +928,7 @@ impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
#[inline]
fn next(&mut self) -> Option<B> {
self.try_for_each(Err).err()
self.iter.find_map(&mut self.f)
}
#[inline]
@ -852,25 +938,17 @@ impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
}
#[inline]
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
let f = &mut self.f;
self.iter.try_fold(init, move |acc, item| match f(item) {
Some(x) => fold(acc, x),
None => Try::from_ok(acc),
})
self.iter.try_fold(init, filter_map_try_fold(&mut self.f, fold))
}
#[inline]
fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
where Fold: FnMut(Acc, Self::Item) -> Acc,
{
let mut f = self.f;
self.iter.fold(init, move |acc, item| match f(item) {
Some(x) => fold(acc, x),
None => acc,
})
self.iter.fold(init, filter_map_fold(self.f, fold))
}
}
@ -880,29 +958,31 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F>
{
#[inline]
fn next_back(&mut self) -> Option<B> {
self.try_rfold((), |_, x| Err(x)).err()
#[inline]
fn find<T, B>(
f: &mut impl FnMut(T) -> Option<B>
) -> impl FnMut((), T) -> LoopState<(), B> + '_ {
move |(), x| match f(x) {
Some(x) => LoopState::Break(x),
None => LoopState::Continue(()),
}
}
self.iter.try_rfold((), find(&mut self.f)).break_value()
}
#[inline]
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
let f = &mut self.f;
self.iter.try_rfold(init, move |acc, item| match f(item) {
Some(x) => fold(acc, x),
None => Try::from_ok(acc),
})
self.iter.try_rfold(init, filter_map_try_fold(&mut self.f, fold))
}
#[inline]
fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
where Fold: FnMut(Acc, Self::Item) -> Acc,
{
let mut f = self.f;
self.iter.rfold(init, move |acc, item| match f(item) {
Some(x) => fold(acc, x),
None => acc,
})
self.iter.rfold(init, filter_map_fold(self.f, fold))
}
}
@ -944,14 +1024,12 @@ impl<I> Iterator for Enumerate<I> where I: Iterator {
///
/// Might panic if the index of the element overflows a `usize`.
#[inline]
#[rustc_inherit_overflow_checks]
fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
self.iter.next().map(|a| {
let ret = (self.count, a);
// Possible undefined overflow.
self.count += 1;
ret
})
let a = self.iter.next()?;
let i = self.count;
// Possible undefined overflow.
AddAssign::add_assign(&mut self.count, 1);
Some((i, a))
}
#[inline]
@ -960,13 +1038,12 @@ impl<I> Iterator for Enumerate<I> where I: Iterator {
}
#[inline]
#[rustc_inherit_overflow_checks]
fn nth(&mut self, n: usize) -> Option<(usize, I::Item)> {
self.iter.nth(n).map(|a| {
let i = self.count + n;
self.count = i + 1;
(i, a)
})
let a = self.iter.nth(n)?;
// Possible undefined overflow.
let i = Add::add(self.count, n);
self.count = Add::add(i, 1);
Some((i, a))
}
#[inline]
@ -975,29 +1052,43 @@ impl<I> Iterator for Enumerate<I> where I: Iterator {
}
#[inline]
#[rustc_inherit_overflow_checks]
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
let count = &mut self.count;
self.iter.try_fold(init, move |acc, item| {
let acc = fold(acc, (*count, item));
*count += 1;
acc
})
#[inline]
fn enumerate<'a, T, Acc, R>(
count: &'a mut usize,
mut fold: impl FnMut(Acc, (usize, T)) -> R + 'a,
) -> impl FnMut(Acc, T) -> R + 'a {
move |acc, item| {
let acc = fold(acc, (*count, item));
// Possible undefined overflow.
AddAssign::add_assign(count, 1);
acc
}
}
self.iter.try_fold(init, enumerate(&mut self.count, fold))
}
#[inline]
#[rustc_inherit_overflow_checks]
fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
where Fold: FnMut(Acc, Self::Item) -> Acc,
{
let mut count = self.count;
self.iter.fold(init, move |acc, item| {
let acc = fold(acc, (count, item));
count += 1;
acc
})
#[inline]
fn enumerate<T, Acc>(
mut count: usize,
mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
) -> impl FnMut(Acc, T) -> Acc {
move |acc, item| {
let acc = fold(acc, (count, item));
// Possible undefined overflow.
AddAssign::add_assign(&mut count, 1);
acc
}
}
self.iter.fold(init, enumerate(self.count, fold))
}
}
@ -1007,48 +1098,60 @@ impl<I> DoubleEndedIterator for Enumerate<I> where
{
#[inline]
fn next_back(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
self.iter.next_back().map(|a| {
let len = self.iter.len();
// Can safely add, `ExactSizeIterator` promises that the number of
// elements fits into a `usize`.
(self.count + len, a)
})
let a = self.iter.next_back()?;
let len = self.iter.len();
// Can safely add, `ExactSizeIterator` promises that the number of
// elements fits into a `usize`.
Some((self.count + len, a))
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<(usize, <I as Iterator>::Item)> {
self.iter.nth_back(n).map(|a| {
let len = self.iter.len();
// Can safely add, `ExactSizeIterator` promises that the number of
// elements fits into a `usize`.
(self.count + len, a)
})
let a = self.iter.nth_back(n)?;
let len = self.iter.len();
// Can safely add, `ExactSizeIterator` promises that the number of
// elements fits into a `usize`.
Some((self.count + len, a))
}
#[inline]
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
// Can safely add and subtract the count, as `ExactSizeIterator` promises
// that the number of elements fits into a `usize`.
let mut count = self.count + self.iter.len();
self.iter.try_rfold(init, move |acc, item| {
count -= 1;
fold(acc, (count, item))
})
fn enumerate<T, Acc, R>(
mut count: usize,
mut fold: impl FnMut(Acc, (usize, T)) -> R,
) -> impl FnMut(Acc, T) -> R {
move |acc, item| {
count -= 1;
fold(acc, (count, item))
}
}
let count = self.count + self.iter.len();
self.iter.try_rfold(init, enumerate(count, fold))
}
#[inline]
fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
where Fold: FnMut(Acc, Self::Item) -> Acc,
{
// Can safely add and subtract the count, as `ExactSizeIterator` promises
// that the number of elements fits into a `usize`.
let mut count = self.count + self.iter.len();
self.iter.rfold(init, move |acc, item| {
count -= 1;
fold(acc, (count, item))
})
fn enumerate<T, Acc>(
mut count: usize,
mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
) -> impl FnMut(Acc, T) -> Acc {
move |acc, item| {
count -= 1;
fold(acc, (count, item))
}
}
let count = self.count + self.iter.len();
self.iter.rfold(init, enumerate(count, fold))
}
}
@ -1162,7 +1265,10 @@ impl<I: Iterator> Iterator for Peekable<I> {
};
let (lo, hi) = self.iter.size_hint();
let lo = lo.saturating_add(peek_len);
let hi = hi.and_then(|x| x.checked_add(peek_len));
let hi = match hi {
Some(x) => x.checked_add(peek_len),
None => None,
};
(lo, hi)
}
@ -1321,16 +1427,23 @@ impl<I: Iterator, P> Iterator for SkipWhile<I, P>
#[inline]
fn next(&mut self) -> Option<I::Item> {
fn check<'a, T>(
flag: &'a mut bool,
pred: &'a mut impl FnMut(&T) -> bool,
) -> impl FnMut(&T) -> bool + 'a {
move |x| {
if *flag || !pred(x) {
*flag = true;
true
} else {
false
}
}
}
let flag = &mut self.flag;
let pred = &mut self.predicate;
self.iter.find(move |x| {
if *flag || !pred(x) {
*flag = true;
true
} else {
false
}
})
self.iter.find(check(flag, pred))
}
#[inline]
@ -1412,14 +1525,13 @@ impl<I: Iterator, P> Iterator for TakeWhile<I, P>
if self.flag {
None
} else {
self.iter.next().and_then(|x| {
if (self.predicate)(&x) {
Some(x)
} else {
self.flag = true;
None
}
})
let x = self.iter.next()?;
if (self.predicate)(&x) {
Some(x)
} else {
self.flag = true;
None
}
}
}
@ -1434,22 +1546,30 @@ impl<I: Iterator, P> Iterator for TakeWhile<I, P>
}
#[inline]
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
if self.flag {
Try::from_ok(init)
} else {
let flag = &mut self.flag;
let p = &mut self.predicate;
self.iter.try_fold(init, move |acc, x|{
fn check<'a, T, Acc, R: Try<Ok = Acc>>(
flag: &'a mut bool,
p: &'a mut impl FnMut(&T) -> bool,
mut fold: impl FnMut(Acc, T) -> R + 'a,
) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
move |acc, x| {
if p(&x) {
LoopState::from_try(fold(acc, x))
} else {
*flag = true;
LoopState::Break(Try::from_ok(acc))
}
}).into_try()
}
}
if self.flag {
Try::from_ok(init)
} else {
let flag = &mut self.flag;
let p = &mut self.predicate;
self.iter.try_fold(init, check(flag, p, fold)).into_try()
}
}
}
@ -1534,7 +1654,10 @@ impl<I> Iterator for Skip<I> where I: Iterator {
let (lower, upper) = self.iter.size_hint();
let lower = lower.saturating_sub(self.n);
let upper = upper.map(|x| x.saturating_sub(self.n));
let upper = match upper {
Some(x) => Some(x.saturating_sub(self.n)),
None => None,
};
(lower, upper)
}
@ -1595,19 +1718,26 @@ impl<I> DoubleEndedIterator for Skip<I> where I: DoubleEndedIterator + ExactSize
}
}
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
let mut n = self.len();
if n == 0 {
Try::from_ok(init)
} else {
self.iter.try_rfold(init, move |acc, x| {
fn check<T, Acc, R: Try<Ok = Acc>>(
mut n: usize,
mut fold: impl FnMut(Acc, T) -> R,
) -> impl FnMut(Acc, T) -> LoopState<Acc, R> {
move |acc, x| {
n -= 1;
let r = fold(acc, x);
if n == 0 { LoopState::Break(r) }
else { LoopState::from_try(r) }
}).into_try()
}
}
let n = self.len();
if n == 0 {
Try::from_ok(init)
} else {
self.iter.try_rfold(init, check(n, fold)).into_try()
}
}
}
@ -1682,19 +1812,26 @@ impl<I> Iterator for Take<I> where I: Iterator{
}
#[inline]
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
if self.n == 0 {
Try::from_ok(init)
} else {
let n = &mut self.n;
self.iter.try_fold(init, move |acc, x| {
fn check<'a, T, Acc, R: Try<Ok = Acc>>(
n: &'a mut usize,
mut fold: impl FnMut(Acc, T) -> R + 'a,
) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
move |acc, x| {
*n -= 1;
let r = fold(acc, x);
if *n == 0 { LoopState::Break(r) }
else { LoopState::from_try(r) }
}).into_try()
}
}
if self.n == 0 {
Try::from_ok(init)
} else {
let n = &mut self.n;
self.iter.try_fold(init, check(n, fold)).into_try()
}
}
}
@ -1793,7 +1930,8 @@ impl<B, I, St, F> Iterator for Scan<I, St, F> where
#[inline]
fn next(&mut self) -> Option<B> {
self.iter.next().and_then(|a| (self.f)(&mut self.state, a))
let a = self.iter.next()?;
(self.f)(&mut self.state, a)
}
#[inline]
@ -1803,17 +1941,25 @@ impl<B, I, St, F> Iterator for Scan<I, St, F> where
}
#[inline]
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
fn scan<'a, T, St, B, Acc, R: Try<Ok = Acc>>(
state: &'a mut St,
f: &'a mut impl FnMut(&mut St, T) -> Option<B>,
mut fold: impl FnMut(Acc, B) -> R + 'a,
) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
move |acc, x| {
match f(state, x) {
None => LoopState::Break(Try::from_ok(acc)),
Some(x) => LoopState::from_try(fold(acc, x)),
}
}
}
let state = &mut self.state;
let f = &mut self.f;
self.iter.try_fold(init, move |acc, x| {
match f(state, x) {
None => LoopState::Break(Try::from_ok(acc)),
Some(x) => LoopState::from_try(fold(acc, x)),
}
}).into_try()
self.iter.try_fold(init, scan(state, f, fold)).into_try()
}
}
@ -2104,6 +2250,20 @@ impl<I: Iterator, F> Inspect<I, F> where F: FnMut(&I::Item) {
}
}
fn inspect_fold<T, Acc>(
mut f: impl FnMut(&T),
mut fold: impl FnMut(Acc, T) -> Acc,
) -> impl FnMut(Acc, T) -> Acc {
move |acc, item| { f(&item); fold(acc, item) }
}
fn inspect_try_fold<'a, T, Acc, R>(
f: &'a mut impl FnMut(&T),
mut fold: impl FnMut(Acc, T) -> R + 'a,
) -> impl FnMut(Acc, T) -> R + 'a {
move |acc, item| { f(&item); fold(acc, item) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator, F> Iterator for Inspect<I, F> where F: FnMut(&I::Item) {
type Item = I::Item;
@ -2120,19 +2280,17 @@ impl<I: Iterator, F> Iterator for Inspect<I, F> where F: FnMut(&I::Item) {
}
#[inline]
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
let f = &mut self.f;
self.iter.try_fold(init, move |acc, item| { f(&item); fold(acc, item) })
self.iter.try_fold(init, inspect_try_fold(&mut self.f, fold))
}
#[inline]
fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
where Fold: FnMut(Acc, Self::Item) -> Acc,
{
let mut f = self.f;
self.iter.fold(init, move |acc, item| { f(&item); fold(acc, item) })
self.iter.fold(init, inspect_fold(self.f, fold))
}
}
@ -2147,19 +2305,17 @@ impl<I: DoubleEndedIterator, F> DoubleEndedIterator for Inspect<I, F>
}
#[inline]
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
{
let f = &mut self.f;
self.iter.try_rfold(init, move |acc, item| { f(&item); fold(acc, item) })
self.iter.try_rfold(init, inspect_try_fold(&mut self.f, fold))
}
#[inline]
fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
where Fold: FnMut(Acc, Self::Item) -> Acc,
{
let mut f = self.f;
self.iter.rfold(init, move |acc, item| { f(&item); fold(acc, item) })
self.iter.rfold(init, inspect_fold(self.f, fold))
}
}

View File

@ -94,11 +94,9 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
#[inline]
default fn next(&mut self) -> Option<(A::Item, B::Item)> {
self.a.next().and_then(|x| {
self.b.next().and_then(|y| {
Some((x, y))
})
})
let x = self.a.next()?;
let y = self.b.next()?;
Some((x, y))
}
#[inline]

View File

@ -394,7 +394,8 @@ impl<A, F: FnOnce() -> A> Iterator for OnceWith<F> {
#[inline]
fn next(&mut self) -> Option<A> {
self.gen.take().map(|f| f())
let f = self.gen.take()?;
Some(f())
}
#[inline]
@ -608,10 +609,9 @@ impl<T, F> Iterator for Successors<T, F>
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.next.take().map(|item| {
self.next = (self.succ)(&item);
item
})
let item = self.next.take()?;
self.next = (self.succ)(&item);
Some(item)
}
#[inline]

View File

@ -85,28 +85,28 @@ macro_rules! float_sum_product {
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl Sum for $a {
fn sum<I: Iterator<Item=$a>>(iter: I) -> $a {
iter.fold(0.0, |a, b| a + b)
iter.fold(0.0, Add::add)
}
}
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl Product for $a {
fn product<I: Iterator<Item=$a>>(iter: I) -> $a {
iter.fold(1.0, |a, b| a * b)
iter.fold(1.0, Mul::mul)
}
}
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl<'a> Sum<&'a $a> for $a {
fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
iter.fold(0.0, |a, b| a + *b)
iter.fold(0.0, Add::add)
}
}
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl<'a> Product<&'a $a> for $a {
fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
iter.fold(1.0, |a, b| a * *b)
iter.fold(1.0, Mul::mul)
}
}
)*)

View File

@ -69,7 +69,7 @@ pub trait DoubleEndedIterator: Iterator {
/// Returns the `n`th element from the end of the iterator.
///
/// This is essentially the reversed version of [`nth`]. Although like most indexing
/// operations, the count starts from zero, so `nth_back(0)` returns the first value fro
/// operations, the count starts from zero, so `nth_back(0)` returns the first value from
/// the end, `nth_back(1)` the second, and so on.
///
/// Note that all elements between the end and the returned element will be
@ -219,12 +219,17 @@ pub trait DoubleEndedIterator: Iterator {
/// ```
#[inline]
#[stable(feature = "iter_rfold", since = "1.27.0")]
fn rfold<B, F>(mut self, accum: B, mut f: F) -> B
fn rfold<B, F>(mut self, accum: B, f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.try_rfold(accum, move |acc, x| Ok::<B, !>(f(acc, x))).unwrap()
#[inline]
fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
move |acc, x| Ok(f(acc, x))
}
self.try_rfold(accum, ok(f)).unwrap()
}
/// Searches for an element of an iterator from the back that satisfies a predicate.
@ -271,15 +276,21 @@ pub trait DoubleEndedIterator: Iterator {
/// ```
#[inline]
#[stable(feature = "iter_rfind", since = "1.27.0")]
fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
where
Self: Sized,
P: FnMut(&Self::Item) -> bool
{
self.try_rfold((), move |(), x| {
if predicate(&x) { LoopState::Break(x) }
else { LoopState::Continue(()) }
}).break_value()
#[inline]
fn check<T>(
mut predicate: impl FnMut(&T) -> bool,
) -> impl FnMut((), T) -> LoopState<(), T> {
move |(), x| {
if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) }
}
}
self.try_rfold((), check(predicate)).break_value()
}
}

View File

@ -1,5 +1,5 @@
use crate::cmp::Ordering;
use crate::ops::Try;
use crate::ops::{Add, Try};
use super::super::LoopState;
use super::super::{Chain, Cycle, Copied, Cloned, Enumerate, Filter, FilterMap, Fuse};
@ -234,11 +234,15 @@ pub trait Iterator {
/// assert_eq!(a.iter().count(), 5);
/// ```
#[inline]
#[rustc_inherit_overflow_checks]
#[stable(feature = "rust1", since = "1.0.0")]
fn count(self) -> usize where Self: Sized {
// Might overflow.
self.fold(0, |cnt, _| cnt + 1)
#[inline]
fn add1<T>(count: usize, _: T) -> usize {
// Might overflow.
Add::add(count, 1)
}
self.fold(0, add1)
}
/// Consumes the iterator, returning the last element.
@ -263,7 +267,12 @@ pub trait Iterator {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn last(self) -> Option<Self::Item> where Self: Sized {
self.fold(None, |_, x| Some(x))
#[inline]
fn some<T>(_: Option<T>, x: T) -> Option<T> {
Some(x)
}
self.fold(None, some)
}
/// Returns the `n`th element of the iterator.
@ -596,10 +605,15 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iterator_for_each", since = "1.21.0")]
fn for_each<F>(self, mut f: F) where
fn for_each<F>(self, f: F) where
Self: Sized, F: FnMut(Self::Item),
{
self.fold((), move |(), item| f(item));
#[inline]
fn call<T>(mut f: impl FnMut(T)) -> impl FnMut((), T) {
move |(), item| f(item)
}
self.fold((), call(f));
}
/// Creates an iterator which uses a closure to determine if an element
@ -1490,21 +1504,30 @@ pub trait Iterator {
/// assert_eq!(odd, vec![1, 3]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn partition<B, F>(self, mut f: F) -> (B, B) where
fn partition<B, F>(self, f: F) -> (B, B) where
Self: Sized,
B: Default + Extend<Self::Item>,
F: FnMut(&Self::Item) -> bool
{
#[inline]
fn extend<'a, T, B: Extend<T>>(
mut f: impl FnMut(&T) -> bool + 'a,
left: &'a mut B,
right: &'a mut B,
) -> impl FnMut(T) + 'a {
move |x| {
if f(&x) {
left.extend(Some(x));
} else {
right.extend(Some(x));
}
}
}
let mut left: B = Default::default();
let mut right: B = Default::default();
self.for_each(|x| {
if f(&x) {
left.extend(Some(x))
} else {
right.extend(Some(x))
}
});
self.for_each(extend(f, &mut left, &mut right));
(left, right)
}
@ -1702,10 +1725,15 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iterator_try_fold", since = "1.27.0")]
fn try_for_each<F, R>(&mut self, mut f: F) -> R where
fn try_for_each<F, R>(&mut self, f: F) -> R where
Self: Sized, F: FnMut(Self::Item) -> R, R: Try<Ok=()>
{
self.try_fold((), move |(), x| f(x))
#[inline]
fn call<T, R>(mut f: impl FnMut(T) -> R) -> impl FnMut((), T) -> R {
move |(), x| f(x)
}
self.try_fold((), call(f))
}
/// An iterator method that applies a function, producing a single, final value.
@ -1777,10 +1805,15 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn fold<B, F>(mut self, init: B, mut f: F) -> B where
fn fold<B, F>(mut self, init: B, f: F) -> B where
Self: Sized, F: FnMut(B, Self::Item) -> B,
{
self.try_fold(init, move |acc, x| Ok::<B, !>(f(acc, x))).unwrap()
#[inline]
fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
move |acc, x| Ok(f(acc, x))
}
self.try_fold(init, ok(f)).unwrap()
}
/// Tests if every element of the iterator matches a predicate.
@ -1822,13 +1855,18 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn all<F>(&mut self, mut f: F) -> bool where
fn all<F>(&mut self, f: F) -> bool where
Self: Sized, F: FnMut(Self::Item) -> bool
{
self.try_for_each(move |x| {
if f(x) { LoopState::Continue(()) }
else { LoopState::Break(()) }
}) == LoopState::Continue(())
#[inline]
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> {
move |x| {
if f(x) { LoopState::Continue(()) }
else { LoopState::Break(()) }
}
}
self.try_for_each(check(f)) == LoopState::Continue(())
}
/// Tests if any element of the iterator matches a predicate.
@ -1870,14 +1908,19 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn any<F>(&mut self, mut f: F) -> bool where
fn any<F>(&mut self, f: F) -> bool where
Self: Sized,
F: FnMut(Self::Item) -> bool
{
self.try_for_each(move |x| {
if f(x) { LoopState::Break(()) }
else { LoopState::Continue(()) }
}) == LoopState::Break(())
#[inline]
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> {
move |x| {
if f(x) { LoopState::Break(()) }
else { LoopState::Continue(()) }
}
}
self.try_for_each(check(f)) == LoopState::Break(())
}
/// Searches for an element of an iterator that satisfies a predicate.
@ -1924,14 +1967,19 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where
Self: Sized,
P: FnMut(&Self::Item) -> bool,
{
self.try_for_each(move |x| {
if predicate(&x) { LoopState::Break(x) }
else { LoopState::Continue(()) }
}).break_value()
#[inline]
fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> LoopState<(), T> {
move |x| {
if predicate(&x) { LoopState::Break(x) }
else { LoopState::Continue(()) }
}
}
self.try_for_each(check(predicate)).break_value()
}
/// Applies function to the elements of iterator and returns
@ -1951,16 +1999,19 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iterator_find_map", since = "1.30.0")]
fn find_map<B, F>(&mut self, mut f: F) -> Option<B> where
fn find_map<B, F>(&mut self, f: F) -> Option<B> where
Self: Sized,
F: FnMut(Self::Item) -> Option<B>,
{
self.try_for_each(move |x| {
match f(x) {
#[inline]
fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut(T) -> LoopState<(), B> {
move |x| match f(x) {
Some(x) => LoopState::Break(x),
None => LoopState::Continue(()),
}
}).break_value()
}
self.try_for_each(check(f)).break_value()
}
/// Searches for an element in an iterator, returning its index.
@ -2018,17 +2069,23 @@ pub trait Iterator {
///
/// ```
#[inline]
#[rustc_inherit_overflow_checks]
#[stable(feature = "rust1", since = "1.0.0")]
fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
fn position<P>(&mut self, predicate: P) -> Option<usize> where
Self: Sized,
P: FnMut(Self::Item) -> bool,
{
// The addition might panic on overflow
self.try_fold(0, move |i, x| {
if predicate(x) { LoopState::Break(i) }
else { LoopState::Continue(i + 1) }
}).break_value()
#[inline]
fn check<T>(
mut predicate: impl FnMut(T) -> bool,
) -> impl FnMut(usize, T) -> LoopState<usize, usize> {
// The addition might panic on overflow
move |i, x| {
if predicate(x) { LoopState::Break(i) }
else { LoopState::Continue(Add::add(i, 1)) }
}
}
self.try_fold(0, check(predicate)).break_value()
}
/// Searches for an element in an iterator from the right, returning its
@ -2071,18 +2128,25 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
fn rposition<P>(&mut self, predicate: P) -> Option<usize> where
P: FnMut(Self::Item) -> bool,
Self: Sized + ExactSizeIterator + DoubleEndedIterator
{
// No need for an overflow check here, because `ExactSizeIterator`
// implies that the number of elements fits into a `usize`.
#[inline]
fn check<T>(
mut predicate: impl FnMut(T) -> bool,
) -> impl FnMut(usize, T) -> LoopState<usize, usize> {
move |i, x| {
let i = i - 1;
if predicate(x) { LoopState::Break(i) }
else { LoopState::Continue(i) }
}
}
let n = self.len();
self.try_rfold(n, move |i, x| {
let i = i - 1;
if predicate(x) { LoopState::Break(i) }
else { LoopState::Continue(i) }
}).break_value()
self.try_rfold(n, check(predicate)).break_value()
}
/// Returns the maximum element of an iterator.
@ -2151,11 +2215,22 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
fn max_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item>
fn max_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item>
where Self: Sized, F: FnMut(&Self::Item) -> B,
{
#[inline]
fn key<T, B>(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) {
move |x| (f(&x), x)
}
// switch to y even if it is only equal, to preserve stability.
select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p <= y_p).map(|(_, x)| x)
#[inline]
fn select<T, B: Ord>((x_p, _): &(B, T), (y_p, _): &(B, T)) -> bool {
x_p <= y_p
}
let (_, x) = select_fold1(self.map(key(f)), select)?;
Some(x)
}
/// Returns the element that gives the maximum value with respect to the
@ -2174,11 +2249,16 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iter_max_by", since = "1.15.0")]
fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
fn max_by<F>(self, compare: F) -> Option<Self::Item>
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
{
// switch to y even if it is only equal, to preserve stability.
select_fold1(self, |x, y| compare(x, y) != Ordering::Greater)
#[inline]
fn select<T>(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(&T, &T) -> bool {
move |x, y| compare(x, y) != Ordering::Greater
}
select_fold1(self, select(compare))
}
/// Returns the element that gives the minimum value from the
@ -2195,12 +2275,24 @@ pub trait Iterator {
/// let a = [-3_i32, 0, 1, 5, -10];
/// assert_eq!(*a.iter().min_by_key(|x| x.abs()).unwrap(), 0);
/// ```
#[inline]
#[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
fn min_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item>
fn min_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item>
where Self: Sized, F: FnMut(&Self::Item) -> B,
{
#[inline]
fn key<T, B>(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) {
move |x| (f(&x), x)
}
// only switch to y if it is strictly smaller, to preserve stability.
select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p > y_p).map(|(_, x)| x)
#[inline]
fn select<T, B: Ord>((x_p, _): &(B, T), (y_p, _): &(B, T)) -> bool {
x_p > y_p
}
let (_, x) = select_fold1(self.map(key(f)), select)?;
Some(x)
}
/// Returns the element that gives the minimum value with respect to the
@ -2219,11 +2311,16 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iter_min_by", since = "1.15.0")]
fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
fn min_by<F>(self, compare: F) -> Option<Self::Item>
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
{
// only switch to y if it is strictly smaller, to preserve stability.
select_fold1(self, |x, y| compare(x, y) == Ordering::Greater)
#[inline]
fn select<T>(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(&T, &T) -> bool {
move |x, y| compare(x, y) == Ordering::Greater
}
select_fold1(self, select(compare))
}
@ -2284,13 +2381,20 @@ pub trait Iterator {
FromB: Default + Extend<B>,
Self: Sized + Iterator<Item=(A, B)>,
{
fn extend<'a, A, B>(
ts: &'a mut impl Extend<A>,
us: &'a mut impl Extend<B>,
) -> impl FnMut((A, B)) + 'a {
move |(t, u)| {
ts.extend(Some(t));
us.extend(Some(u));
}
}
let mut ts: FromA = Default::default();
let mut us: FromB = Default::default();
self.for_each(|(t, u)| {
ts.extend(Some(t));
us.extend(Some(u));
});
self.for_each(extend(&mut ts, &mut us));
(ts, us)
}
@ -2617,7 +2721,7 @@ pub trait Iterator {
Self: Sized,
Self::Item: PartialOrd,
{
self.is_sorted_by(|a, b| a.partial_cmp(b))
self.is_sorted_by(PartialOrd::partial_cmp)
}
/// Checks if the elements of this iterator are sorted using the given comparator function.
@ -2639,10 +2743,7 @@ pub trait Iterator {
};
while let Some(curr) = self.next() {
if compare(&last, &curr)
.map(|o| o == Ordering::Greater)
.unwrap_or(true)
{
if let Some(Ordering::Greater) | None = compare(&last, &curr) {
return false;
}
last = curr;
@ -2687,17 +2788,21 @@ pub trait Iterator {
/// commonalities of {max,min}{,_by}. In particular, this avoids
/// having to implement optimizations several times.
#[inline]
fn select_fold1<I, F>(mut it: I, mut f: F) -> Option<I::Item>
fn select_fold1<I, F>(mut it: I, f: F) -> Option<I::Item>
where
I: Iterator,
F: FnMut(&I::Item, &I::Item) -> bool,
{
#[inline]
fn select<T>(mut f: impl FnMut(&T, &T) -> bool) -> impl FnMut(T, T) -> T {
move |sel, x| if f(&sel, &x) { x } else { sel }
}
// start with the first element as our selection. This avoids
// having to use `Option`s inside the loop, translating to a
// sizeable performance gain (6x in one case).
it.next().map(|first| {
it.fold(first, |sel, x| if f(&sel, &x) { x } else { sel })
})
let first = it.next()?;
Some(it.fold(first, select(f)))
}
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -63,7 +63,7 @@
#![warn(missing_debug_implementations)]
#![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings
#![allow(explicit_outlives_requirements)]
#![cfg_attr(not(bootstrap), allow(incomplete_features))]
#![allow(incomplete_features)]
#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
@ -129,7 +129,7 @@
#![feature(structural_match)]
#![feature(abi_unadjusted)]
#![feature(adx_target_feature)]
#![feature(maybe_uninit_slice, maybe_uninit_array)]
#![feature(maybe_uninit_slice)]
#![feature(external_doc)]
#![feature(mem_take)]
#![feature(associated_type_bounds)]

View File

@ -2,21 +2,21 @@
///
/// For details, see `std::macros`.
#[macro_export]
#[allow_internal_unstable(core_panic, __rust_unstable_column)]
#[allow_internal_unstable(core_panic)]
#[stable(feature = "core", since = "1.6.0")]
macro_rules! panic {
() => (
$crate::panic!("explicit panic")
);
($msg:expr) => ({
$crate::panicking::panic(&($msg, file!(), line!(), __rust_unstable_column!()))
$crate::panicking::panic(&($msg, $crate::file!(), $crate::line!(), $crate::column!()))
});
($msg:expr,) => (
$crate::panic!($msg)
);
($fmt:expr, $($arg:tt)+) => ({
$crate::panicking::panic_fmt(format_args!($fmt, $($arg)+),
&(file!(), line!(), __rust_unstable_column!()))
$crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+),
&($crate::file!(), $crate::line!(), $crate::column!()))
});
}
@ -70,7 +70,7 @@ macro_rules! assert_eq {
panic!(r#"assertion failed: `(left == right)`
left: `{:?}`,
right: `{:?}`: {}"#, &*left_val, &*right_val,
format_args!($($arg)+))
$crate::format_args!($($arg)+))
}
}
}
@ -127,7 +127,7 @@ macro_rules! assert_ne {
panic!(r#"assertion failed: `(left != right)`
left: `{:?}`,
right: `{:?}`: {}"#, &*left_val, &*right_val,
format_args!($($arg)+))
$crate::format_args!($($arg)+))
}
}
}
@ -181,7 +181,7 @@ macro_rules! assert_ne {
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! debug_assert {
($($arg:tt)*) => (if cfg!(debug_assertions) { assert!($($arg)*); })
($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert!($($arg)*); })
}
/// Asserts that two expressions are equal to each other.
@ -208,7 +208,7 @@ macro_rules! debug_assert {
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! debug_assert_eq {
($($arg:tt)*) => (if cfg!(debug_assertions) { $crate::assert_eq!($($arg)*); })
($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_eq!($($arg)*); })
}
/// Asserts that two expressions are not equal to each other.
@ -235,7 +235,7 @@ macro_rules! debug_assert_eq {
#[macro_export]
#[stable(feature = "assert_ne", since = "1.13.0")]
macro_rules! debug_assert_ne {
($($arg:tt)*) => (if cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); })
($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); })
}
/// Unwraps a result or propagates its error.
@ -386,7 +386,7 @@ macro_rules! r#try {
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! write {
($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
($dst:expr, $($arg:tt)*) => ($dst.write_fmt($crate::format_args!($($arg)*)))
}
/// Write formatted data into a buffer, with a newline appended.
@ -446,7 +446,7 @@ macro_rules! writeln {
$crate::writeln!($dst)
);
($dst:expr, $($arg:tt)*) => (
$dst.write_fmt(format_args_nl!($($arg)*))
$dst.write_fmt($crate::format_args_nl!($($arg)*))
);
}
@ -515,7 +515,7 @@ macro_rules! unreachable {
$crate::unreachable!($msg)
});
($fmt:expr, $($arg:tt)*) => ({
panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
});
}
@ -573,7 +573,7 @@ macro_rules! unreachable {
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! unimplemented {
() => (panic!("not yet implemented"));
($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)+)));
($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+)));
}
/// Indicates unfinished code.
@ -632,41 +632,7 @@ macro_rules! unimplemented {
#[unstable(feature = "todo_macro", issue = "59277")]
macro_rules! todo {
() => (panic!("not yet implemented"));
($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)+)));
}
/// Creates an array of [`MaybeUninit`].
///
/// This macro constructs an uninitialized array of the type `[MaybeUninit<K>; N]`.
/// It exists solely because bootstrap does not yet support const array-init expressions.
///
/// [`MaybeUninit`]: mem/union.MaybeUninit.html
// FIXME: Remove both versions of this macro once bootstrap is 1.38.
#[macro_export]
#[unstable(feature = "maybe_uninit_array", issue = "53491")]
#[cfg(bootstrap)]
macro_rules! uninit_array {
// This `assume_init` is safe because an array of `MaybeUninit` does not
// require initialization.
($t:ty; $size:expr) => (unsafe {
MaybeUninit::<[MaybeUninit<$t>; $size]>::uninit().assume_init()
});
}
/// Creates an array of [`MaybeUninit`].
///
/// This macro constructs an uninitialized array of the type `[MaybeUninit<K>; N]`.
/// It exists solely because bootstrap does not yet support const array-init expressions.
///
/// [`MaybeUninit`]: mem/union.MaybeUninit.html
// FIXME: Just inline this version of the macro once bootstrap is 1.38.
#[macro_export]
#[unstable(feature = "maybe_uninit_array", issue = "53491")]
#[cfg(not(bootstrap))]
macro_rules! uninit_array {
($t:ty; $size:expr) => (
[MaybeUninit::<$t>::UNINIT; $size]
);
($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+)));
}
/// Definitions of built-in macros.
@ -674,7 +640,6 @@ macro_rules! uninit_array {
/// Most of the macro properties (stability, visibility, etc.) are taken from the source code here,
/// with exception of expansion functions transforming macro inputs into outputs,
/// those functions are provided by the compiler.
#[cfg(not(bootstrap))]
pub(crate) mod builtin {
/// Causes compilation to fail with the given error message when encountered.
@ -962,13 +927,6 @@ pub(crate) mod builtin {
#[macro_export]
macro_rules! column { () => { /* compiler built-in */ } }
/// Same as `column`, but less likely to be shadowed.
#[unstable(feature = "__rust_unstable_column", issue = "0",
reason = "internal implementation detail of the `panic` macro")]
#[rustc_builtin_macro]
#[macro_export]
macro_rules! __rust_unstable_column { () => { /* compiler built-in */ } }
/// Expands to the file name in which it was invoked.
///
/// With [`line!`] and [`column!`], these macros provide debugging information for
@ -1305,14 +1263,14 @@ pub(crate) mod builtin {
/// Unstable implementation detail of the `rustc` compiler, do not use.
#[rustc_builtin_macro]
#[rustc_macro_transparency = "semitransparent"]
#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(core_intrinsics, libstd_sys_internals)]
pub macro RustcDecodable($item:item) { /* compiler built-in */ }
/// Unstable implementation detail of the `rustc` compiler, do not use.
#[rustc_builtin_macro]
#[rustc_macro_transparency = "semitransparent"]
#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(core_intrinsics)]
pub macro RustcEncodable($item:item) { /* compiler built-in */ }

View File

@ -289,9 +289,8 @@ pub trait Copy : Clone {
}
/// Derive macro generating an impl of the trait `Copy`.
#[cfg(not(bootstrap))]
#[rustc_builtin_macro]
#[rustc_macro_transparency = "semitransparent"]
#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")]
#[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 */ }

View File

@ -213,7 +213,7 @@ use crate::mem::ManuallyDrop;
#[allow(missing_debug_implementations)]
#[stable(feature = "maybe_uninit", since = "1.36.0")]
// Lang item so we can wrap other types in it. This is useful for generators.
#[cfg_attr(not(bootstrap), lang = "maybe_uninit")]
#[lang = "maybe_uninit"]
#[derive(Copy)]
#[repr(transparent)]
pub union MaybeUninit<T> {
@ -312,7 +312,7 @@ impl<T> MaybeUninit<T> {
/// without dropping it, so be careful not to use this twice unless you want to
/// skip running the destructor. For your convenience, this also returns a mutable
/// reference to the (now safely initialized) contents of `self`.
#[unstable(feature = "maybe_uninit_extra", issue = "53491")]
#[unstable(feature = "maybe_uninit_extra", issue = "63567")]
#[inline(always)]
pub fn write(&mut self, val: T) -> &mut T {
unsafe {
@ -502,7 +502,7 @@ impl<T> MaybeUninit<T> {
/// // We now created two copies of the same vector, leading to a double-free when
/// // they both get dropped!
/// ```
#[unstable(feature = "maybe_uninit_extra", issue = "53491")]
#[unstable(feature = "maybe_uninit_extra", issue = "63567")]
#[inline(always)]
pub unsafe fn read(&self) -> T {
intrinsics::panic_if_uninhabited::<T>();
@ -516,7 +516,7 @@ impl<T> MaybeUninit<T> {
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
/// state. Calling this when the content is not yet fully initialized causes undefined
/// behavior.
#[unstable(feature = "maybe_uninit_ref", issue = "53491")]
#[unstable(feature = "maybe_uninit_ref", issue = "63568")]
#[inline(always)]
pub unsafe fn get_ref(&self) -> &T {
&*self.value
@ -532,21 +532,21 @@ impl<T> MaybeUninit<T> {
// FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references
// to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make
// a final decision about the rules before stabilization.
#[unstable(feature = "maybe_uninit_ref", issue = "53491")]
#[unstable(feature = "maybe_uninit_ref", issue = "63568")]
#[inline(always)]
pub unsafe fn get_mut(&mut self) -> &mut T {
&mut *self.value
}
/// Gets a pointer to the first element of the array.
#[unstable(feature = "maybe_uninit_slice", issue = "53491")]
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[inline(always)]
pub fn first_ptr(this: &[MaybeUninit<T>]) -> *const T {
this as *const [MaybeUninit<T>] as *const T
}
/// Gets a mutable pointer to the first element of the array.
#[unstable(feature = "maybe_uninit_slice", issue = "53491")]
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[inline(always)]
pub fn first_ptr_mut(this: &mut [MaybeUninit<T>]) -> *mut T {
this as *mut [MaybeUninit<T>] as *mut T

View File

@ -453,7 +453,7 @@ pub const fn needs_drop<T>() -> bool {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(bootstrap, allow(deprecated_in_future))]
#[allow(deprecated_in_future)]
#[allow(deprecated)]
pub unsafe fn zeroed<T>() -> T {
intrinsics::panic_if_uninhabited::<T>();
@ -481,7 +481,7 @@ pub unsafe fn zeroed<T>() -> T {
#[inline]
#[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(bootstrap, allow(deprecated_in_future))]
#[allow(deprecated_in_future)]
#[allow(deprecated)]
pub unsafe fn uninitialized<T>() -> T {
intrinsics::panic_if_uninhabited::<T>();

View File

@ -1112,7 +1112,13 @@ $EndFeature, "
without modifying the original"]
#[inline]
pub const fn wrapping_add(self, rhs: Self) -> Self {
intrinsics::overflowing_add(self, rhs)
#[cfg(boostrap_stdarch_ignore_this)] {
intrinsics::overflowing_add(self, rhs)
}
#[cfg(not(boostrap_stdarch_ignore_this))] {
intrinsics::wrapping_add(self, rhs)
}
}
}
@ -1135,7 +1141,13 @@ $EndFeature, "
without modifying the original"]
#[inline]
pub const fn wrapping_sub(self, rhs: Self) -> Self {
intrinsics::overflowing_sub(self, rhs)
#[cfg(boostrap_stdarch_ignore_this)] {
intrinsics::overflowing_sub(self, rhs)
}
#[cfg(not(boostrap_stdarch_ignore_this))] {
intrinsics::wrapping_sub(self, rhs)
}
}
}
@ -1157,7 +1169,13 @@ $EndFeature, "
without modifying the original"]
#[inline]
pub const fn wrapping_mul(self, rhs: Self) -> Self {
intrinsics::overflowing_mul(self, rhs)
#[cfg(boostrap_stdarch_ignore_this)] {
intrinsics::overflowing_mul(self, rhs)
}
#[cfg(not(boostrap_stdarch_ignore_this))] {
intrinsics::wrapping_mul(self, rhs)
}
}
}
@ -3031,7 +3049,13 @@ $EndFeature, "
without modifying the original"]
#[inline]
pub const fn wrapping_add(self, rhs: Self) -> Self {
intrinsics::overflowing_add(self, rhs)
#[cfg(boostrap_stdarch_ignore_this)] {
intrinsics::overflowing_add(self, rhs)
}
#[cfg(not(boostrap_stdarch_ignore_this))] {
intrinsics::wrapping_add(self, rhs)
}
}
}
@ -3053,7 +3077,13 @@ $EndFeature, "
without modifying the original"]
#[inline]
pub const fn wrapping_sub(self, rhs: Self) -> Self {
intrinsics::overflowing_sub(self, rhs)
#[cfg(boostrap_stdarch_ignore_this)] {
intrinsics::overflowing_sub(self, rhs)
}
#[cfg(not(boostrap_stdarch_ignore_this))] {
intrinsics::wrapping_sub(self, rhs)
}
}
}
@ -3076,7 +3106,13 @@ $EndFeature, "
without modifying the original"]
#[inline]
pub const fn wrapping_mul(self, rhs: Self) -> Self {
intrinsics::overflowing_mul(self, rhs)
#[cfg(boostrap_stdarch_ignore_this)] {
intrinsics::overflowing_mul(self, rhs)
}
#[cfg(not(boostrap_stdarch_ignore_this))] {
intrinsics::wrapping_mul(self, rhs)
}
}
doc_comment! {

View File

@ -46,20 +46,16 @@ pub use crate::option::Option::{self, Some, None};
pub use crate::result::Result::{self, Ok, Err};
// Re-exported built-in macros
#[cfg(not(bootstrap))]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[doc(no_inline)]
pub use crate::fmt::macros::Debug;
#[cfg(not(bootstrap))]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[doc(no_inline)]
pub use crate::hash::macros::Hash;
#[cfg(not(bootstrap))]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[doc(no_inline)]
pub use crate::{
__rust_unstable_column,
asm,
assert,
cfg,
@ -83,7 +79,6 @@ pub use crate::{
trace_macros,
};
#[cfg(not(bootstrap))]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow(deprecated)]
#[doc(no_inline)]

View File

@ -81,6 +81,34 @@ impl<T, E> Poll<Result<T, E>> {
}
}
impl<T, E> Poll<Option<Result<T, E>>> {
/// Changes the success value of this `Poll` with the closure provided.
#[unstable(feature = "poll_map", issue = "63514")]
pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
where F: FnOnce(T) -> U
{
match self {
Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))),
Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
Poll::Ready(None) => Poll::Ready(None),
Poll::Pending => Poll::Pending,
}
}
/// Changes the error value of this `Poll` with the closure provided.
#[unstable(feature = "poll_map", issue = "63514")]
pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
where F: FnOnce(E) -> U
{
match self {
Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))),
Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))),
Poll::Ready(None) => Poll::Ready(None),
Poll::Pending => Poll::Pending,
}
}
}
#[stable(feature = "futures_api", since = "1.36.0")]
impl<T> From<T> for Poll<T> {
fn from(t: T) -> Poll<T> {

View File

@ -103,6 +103,22 @@ fn test_iterator_chain_nth() {
assert_eq!(it.next(), None);
}
#[test]
fn test_iterator_chain_nth_back() {
let xs = [0, 1, 2, 3, 4, 5];
let ys = [30, 40, 50, 60];
let zs = [];
let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
for (i, x) in expected.iter().rev().enumerate() {
assert_eq!(Some(x), xs.iter().chain(&ys).nth_back(i));
}
assert_eq!(zs.iter().chain(&xs).nth_back(0), Some(&5));
let mut it = xs.iter().chain(&zs);
assert_eq!(it.nth_back(5), Some(&0));
assert_eq!(it.next(), None);
}
#[test]
fn test_iterator_chain_last() {
let xs = [0, 1, 2, 3, 4, 5];
@ -1136,6 +1152,18 @@ fn test_cycle() {
assert_eq!(empty::<i32>().cycle().fold(0, |acc, x| acc + x), 0);
assert_eq!(once(1).cycle().skip(1).take(4).fold(0, |acc, x| acc + x), 4);
assert_eq!((0..10).cycle().take(5).sum::<i32>(), 10);
assert_eq!((0..10).cycle().take(15).sum::<i32>(), 55);
assert_eq!((0..10).cycle().take(25).sum::<i32>(), 100);
let mut iter = (0..10).cycle();
iter.nth(14);
assert_eq!(iter.take(8).sum::<i32>(), 38);
let mut iter = (0..10).cycle();
iter.nth(9);
assert_eq!(iter.take(3).sum::<i32>(), 3);
}
#[test]

View File

@ -136,7 +136,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
}
PatKind::Struct(_, ref subpats, _) => {
let pats_exit = self.pats_all(subpats.iter().map(|f| &f.node.pat), pred);
let pats_exit = self.pats_all(subpats.iter().map(|f| &f.pat), pred);
self.add_ast_node(pat.hir_id.local_id, &[pats_exit])
}

View File

@ -336,7 +336,7 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
fn is_c_like_enum(item: &hir::Item) -> bool {
if let hir::ItemKind::Enum(ref def, _) = item.node {
for variant in &def.variants {
match variant.node.data {
match variant.data {
hir::VariantData::Unit(..) => { /* continue */ }
_ => { return false; }
}

View File

@ -577,15 +577,15 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
variant: &'v Variant,
generics: &'v Generics,
parent_item_id: HirId) {
visitor.visit_ident(variant.node.ident);
visitor.visit_id(variant.node.id);
visitor.visit_variant_data(&variant.node.data,
variant.node.ident.name,
visitor.visit_ident(variant.ident);
visitor.visit_id(variant.id);
visitor.visit_variant_data(&variant.data,
variant.ident.name,
generics,
parent_item_id,
variant.span);
walk_list!(visitor, visit_anon_const, &variant.node.disr_expr);
walk_list!(visitor, visit_attribute, &variant.node.attrs);
walk_list!(visitor, visit_anon_const, &variant.disr_expr);
walk_list!(visitor, visit_attribute, &variant.attrs);
}
pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
@ -704,9 +704,9 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
PatKind::Struct(ref qpath, ref fields, _) => {
visitor.visit_qpath(qpath, pattern.hir_id, pattern.span);
for field in fields {
visitor.visit_id(field.node.hir_id);
visitor.visit_ident(field.node.ident);
visitor.visit_pat(&field.node.pat)
visitor.visit_id(field.hir_id);
visitor.visit_ident(field.ident);
visitor.visit_pat(&field.pat)
}
}
PatKind::Tuple(ref tuple_elements, _) => {

View File

@ -67,7 +67,7 @@ use syntax::errors;
use syntax::ext::base::SpecialDerives;
use syntax::ext::hygiene::ExpnId;
use syntax::print::pprust;
use syntax::source_map::{respan, ExpnInfo, ExpnKind, DesugaringKind, Spanned};
use syntax::source_map::{respan, ExpnData, ExpnKind, DesugaringKind, Spanned};
use syntax::symbol::{kw, sym, Symbol};
use syntax::tokenstream::{TokenStream, TokenTree};
use syntax::parse::token::{self, Token};
@ -136,7 +136,10 @@ pub struct LoweringContext<'a> {
/// When `is_collectin_in_band_lifetimes` is true, each lifetime is checked
/// against this list to see if it is already in-scope, or if a definition
/// needs to be created for it.
in_scope_lifetimes: Vec<Ident>,
///
/// We always store a `modern()` version of the param-name in this
/// vector.
in_scope_lifetimes: Vec<ParamName>,
current_module: NodeId,
@ -337,49 +340,6 @@ enum AnonymousLifetimeMode {
/// Pass responsibility to `resolve_lifetime` code for all cases.
PassThrough,
/// Used in the return types of `async fn` where there exists
/// exactly one argument-position elided lifetime.
///
/// In `async fn`, we lower the arguments types using the `CreateParameter`
/// mode, meaning that non-`dyn` elided lifetimes are assigned a fresh name.
/// If any corresponding elided lifetimes appear in the output, we need to
/// replace them with references to the fresh name assigned to the corresponding
/// elided lifetime in the arguments.
///
/// For **Modern cases**, replace the anonymous parameter with a
/// reference to a specific freshly-named lifetime that was
/// introduced in argument
///
/// For **Dyn Bound** cases, pass responsibility to
/// `resole_lifetime` code.
Replace(LtReplacement),
}
/// The type of elided lifetime replacement to perform on `async fn` return types.
#[derive(Copy, Clone)]
enum LtReplacement {
/// Fresh name introduced by the single non-dyn elided lifetime
/// in the arguments of the async fn.
Some(ParamName),
/// There is no single non-dyn elided lifetime because no lifetimes
/// appeared in the arguments.
NoLifetimes,
/// There is no single non-dyn elided lifetime because multiple
/// lifetimes appeared in the arguments.
MultipleLifetimes,
}
/// Calculates the `LtReplacement` to use for elided lifetimes in the return
/// type based on the fresh elided lifetimes introduced in argument position.
fn get_elided_lt_replacement(arg_position_lifetimes: &[(Span, ParamName)]) -> LtReplacement {
match arg_position_lifetimes {
[] => LtReplacement::NoLifetimes,
[(_span, param)] => LtReplacement::Some(*param),
_ => LtReplacement::MultipleLifetimes,
}
}
struct ImplTraitTypeIdVisitor<'a> { ids: &'a mut SmallVec<[NodeId; 1]> }
@ -744,10 +704,9 @@ impl<'a> LoweringContext<'a> {
span: Span,
allow_internal_unstable: Option<Lrc<[Symbol]>>,
) -> Span {
span.fresh_expansion(ExpnId::root(), ExpnInfo {
def_site: span,
span.fresh_expansion(ExpnData {
allow_internal_unstable,
..ExpnInfo::default(ExpnKind::Desugaring(reason), span, self.sess.edition())
..ExpnData::default(ExpnKind::Desugaring(reason), span, self.sess.edition())
})
}
@ -865,7 +824,7 @@ impl<'a> LoweringContext<'a> {
return;
}
if self.in_scope_lifetimes.contains(&ident.modern()) {
if self.in_scope_lifetimes.contains(&ParamName::Plain(ident.modern())) {
return;
}
@ -899,7 +858,7 @@ impl<'a> LoweringContext<'a> {
{
let old_len = self.in_scope_lifetimes.len();
let lt_def_names = params.iter().filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => Some(param.ident.modern()),
GenericParamKind::Lifetime { .. } => Some(ParamName::Plain(param.ident.modern())),
_ => None,
});
self.in_scope_lifetimes.extend(lt_def_names);
@ -1264,7 +1223,7 @@ impl<'a> LoweringContext<'a> {
P(hir::Path {
res,
segments: hir_vec![hir::PathSegment::from_ident(
Ident::with_empty_ctxt(kw::SelfUpper)
Ident::with_dummy_span(kw::SelfUpper)
)],
span: t.span,
}),
@ -1598,7 +1557,7 @@ impl<'a> LoweringContext<'a> {
let (name, kind) = match name {
hir::LifetimeName::Underscore => (
hir::ParamName::Plain(Ident::with_empty_ctxt(kw::UnderscoreLifetime)),
hir::ParamName::Plain(Ident::with_dummy_span(kw::UnderscoreLifetime)),
hir::LifetimeParamKind::Elided,
),
hir::LifetimeName::Param(param_name) => (
@ -1953,8 +1912,7 @@ impl<'a> LoweringContext<'a> {
err.emit();
}
AnonymousLifetimeMode::PassThrough |
AnonymousLifetimeMode::ReportError |
AnonymousLifetimeMode::Replace(_) => {
AnonymousLifetimeMode::ReportError => {
self.sess.buffer_lint_with_diagnostic(
ELIDED_LIFETIMES_IN_PATHS,
CRATE_NODE_ID,
@ -2043,7 +2001,7 @@ impl<'a> LoweringContext<'a> {
bindings: hir_vec![
hir::TypeBinding {
hir_id: this.next_id(),
ident: Ident::with_empty_ctxt(FN_OUTPUT_NAME),
ident: Ident::with_dummy_span(FN_OUTPUT_NAME),
kind: hir::TypeBindingKind::Equality {
ty: output
.as_ref()
@ -2141,7 +2099,6 @@ impl<'a> LoweringContext<'a> {
// Remember how many lifetimes were already around so that we can
// only look at the lifetime parameters introduced by the arguments.
let lifetime_count_before_args = self.lifetimes_to_define.len();
let inputs = self.with_anonymous_lifetime_mode(lt_mode, |this| {
decl.inputs
.iter()
@ -2156,16 +2113,10 @@ impl<'a> LoweringContext<'a> {
});
let output = if let Some(ret_id) = make_ret_async {
// Calculate the `LtReplacement` to use for any return-position elided
// lifetimes based on the elided lifetime parameters introduced in the args.
let lt_replacement = get_elided_lt_replacement(
&self.lifetimes_to_define[lifetime_count_before_args..]
);
self.lower_async_fn_ret_ty(
&decl.output,
in_band_ty_params.expect("`make_ret_async` but no `fn_def_id`").0,
ret_id,
lt_replacement,
)
} else {
match decl.output {
@ -2230,7 +2181,6 @@ impl<'a> LoweringContext<'a> {
output: &FunctionRetTy,
fn_def_id: DefId,
opaque_ty_node_id: NodeId,
elided_lt_replacement: LtReplacement,
) -> hir::FunctionRetTy {
let span = output.span();
@ -2248,9 +2198,65 @@ impl<'a> LoweringContext<'a> {
self.allocate_hir_id_counter(opaque_ty_node_id);
// When we create the opaque type for this async fn, it is going to have
// to capture all the lifetimes involved in the signature (including in the
// return type). This is done by introducing lifetime parameters for:
//
// - all the explicitly declared lifetimes from the impl and function itself;
// - all the elided lifetimes in the fn arguments;
// - all the elided lifetimes in the return type.
//
// So for example in this snippet:
//
// ```rust
// impl<'a> Foo<'a> {
// async fn bar<'b>(&self, x: &'b Vec<f64>, y: &str) -> &u32 {
// // ^ '0 ^ '1 ^ '2
// // elided lifetimes used below
// }
// }
// ```
//
// we would create an opaque type like:
//
// ```
// type Bar<'a, 'b, '0, '1, '2> = impl Future<Output = &'2 u32>;
// ```
//
// and we would then desugar `bar` to the equivalent of:
//
// ```rust
// impl<'a> Foo<'a> {
// fn bar<'b, '0, '1>(&'0 self, x: &'b Vec<f64>, y: &'1 str) -> Bar<'a, 'b, '0, '1, '_>
// }
// ```
//
// Note that the final parameter to `Bar` is `'_`, not `'2` --
// this is because the elided lifetimes from the return type
// should be figured out using the ordinary elision rules, and
// this desugaring achieves that.
//
// The variable `input_lifetimes_count` tracks the number of
// lifetime parameters to the opaque type *not counting* those
// lifetimes elided in the return type. This includes those
// that are explicitly declared (`in_scope_lifetimes`) and
// those elided lifetimes we found in the arguments (current
// content of `lifetimes_to_define`). Next, we will process
// the return type, which will cause `lifetimes_to_define` to
// grow.
let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len();
let (opaque_ty_id, lifetime_params) = self.with_hir_id_owner(opaque_ty_node_id, |this| {
// We have to be careful to get elision right here. The
// idea is that we create a lifetime parameter for each
// lifetime in the return type. So, given a return type
// like `async fn foo(..) -> &[&u32]`, we lower to `impl
// Future<Output = &'1 [ &'2 u32 ]>`.
//
// Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
// hence the elision takes place at the fn site.
let future_bound = this.with_anonymous_lifetime_mode(
AnonymousLifetimeMode::Replace(elided_lt_replacement),
AnonymousLifetimeMode::CreateParameter,
|this| this.lower_async_fn_output_type_to_future_bound(
output,
fn_def_id,
@ -2267,10 +2273,14 @@ impl<'a> LoweringContext<'a> {
let lifetime_params: Vec<(Span, ParamName)> =
this.in_scope_lifetimes
.iter().cloned()
.map(|ident| (ident.span, ParamName::Plain(ident)))
.map(|name| (name.ident().span, name))
.chain(this.lifetimes_to_define.iter().cloned())
.collect();
debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", this.in_scope_lifetimes);
debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define);
debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params);
let generic_params =
lifetime_params
.iter().cloned()
@ -2304,19 +2314,52 @@ impl<'a> LoweringContext<'a> {
(opaque_ty_id, lifetime_params)
});
let generic_args =
lifetime_params
.iter().cloned()
.map(|(span, hir_name)| {
GenericArg::Lifetime(hir::Lifetime {
hir_id: self.next_id(),
span,
name: hir::LifetimeName::Param(hir_name),
})
// As documented above on the variable
// `input_lifetimes_count`, we need to create the lifetime
// arguments to our opaque type. Continuing with our example,
// we're creating the type arguments for the return type:
//
// ```
// Bar<'a, 'b, '0, '1, '_>
// ```
//
// For the "input" lifetime parameters, we wish to create
// references to the parameters themselves, including the
// "implicit" ones created from parameter types (`'a`, `'b`,
// '`0`, `'1`).
//
// For the "output" lifetime parameters, we just want to
// generate `'_`.
let mut generic_args: Vec<_> =
lifetime_params[..input_lifetimes_count]
.iter()
.map(|&(span, hir_name)| {
// Input lifetime like `'a` or `'1`:
GenericArg::Lifetime(hir::Lifetime {
hir_id: self.next_id(),
span,
name: hir::LifetimeName::Param(hir_name),
})
.collect();
})
.collect();
generic_args.extend(
lifetime_params[input_lifetimes_count..]
.iter()
.map(|&(span, _)| {
// Output lifetime like `'_`.
GenericArg::Lifetime(hir::Lifetime {
hir_id: self.next_id(),
span,
name: hir::LifetimeName::Implicit,
})
})
);
let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args);
// Create the `Foo<...>` refernece itself. Note that the `type
// Foo = impl Trait` is, internally, created as a child of the
// async fn, so the *type parameters* are inherited. It's
// only the lifetime parameters that we must supply.
let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args.into());
hir::FunctionRetTy::Return(P(hir::Ty {
node: opaque_ty_ref,
@ -2350,7 +2393,7 @@ impl<'a> LoweringContext<'a> {
let future_params = P(hir::GenericArgs {
args: hir_vec![],
bindings: hir_vec![hir::TypeBinding {
ident: Ident::with_empty_ctxt(FN_OUTPUT_NAME),
ident: Ident::with_dummy_span(FN_OUTPUT_NAME),
kind: hir::TypeBindingKind::Equality {
ty: output_ty,
},
@ -2412,11 +2455,6 @@ impl<'a> LoweringContext<'a> {
}
AnonymousLifetimeMode::ReportError => self.new_error_lifetime(Some(l.id), span),
AnonymousLifetimeMode::Replace(replacement) => {
let hir_id = self.lower_node_id(l.id);
self.replace_elided_lifetime(hir_id, span, replacement)
}
},
ident => {
self.maybe_collect_in_band_lifetime(ident);
@ -2439,39 +2477,6 @@ impl<'a> LoweringContext<'a> {
}
}
/// Replace a return-position elided lifetime with the elided lifetime
/// from the arguments.
fn replace_elided_lifetime(
&mut self,
hir_id: hir::HirId,
span: Span,
replacement: LtReplacement,
) -> hir::Lifetime {
let multiple_or_none = match replacement {
LtReplacement::Some(name) => {
return hir::Lifetime {
hir_id,
span,
name: hir::LifetimeName::Param(name),
};
}
LtReplacement::MultipleLifetimes => "multiple",
LtReplacement::NoLifetimes => "none",
};
let mut err = crate::middle::resolve_lifetime::report_missing_lifetime_specifiers(
self.sess,
span,
1,
);
err.note(&format!(
"return-position elided lifetimes require exactly one \
input-position elided lifetime, found {}.", multiple_or_none));
err.emit();
hir::Lifetime { hir_id, span, name: hir::LifetimeName::Error }
}
fn lower_generic_params(
&mut self,
params: &[GenericParam],
@ -2685,16 +2690,12 @@ impl<'a> LoweringContext<'a> {
let fs = fields
.iter()
.map(|f| {
Spanned {
span: f.span,
node: hir::FieldPat {
hir_id: self.next_id(),
ident: f.node.ident,
pat: self.lower_pat(&f.node.pat),
is_shorthand: f.node.is_shorthand,
},
}
.map(|f| hir::FieldPat {
hir_id: self.next_id(),
ident: f.ident,
pat: self.lower_pat(&f.pat),
is_shorthand: f.is_shorthand,
span: f.span,
})
.collect();
hir::PatKind::Struct(qpath, fs, etc)
@ -3174,10 +3175,6 @@ impl<'a> LoweringContext<'a> {
AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span),
AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
AnonymousLifetimeMode::Replace(replacement) => {
self.new_replacement_lifetime(replacement, span)
}
}
}
@ -3231,10 +3228,6 @@ impl<'a> LoweringContext<'a> {
// This is the normal case.
AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
AnonymousLifetimeMode::Replace(replacement) => {
self.new_replacement_lifetime(replacement, span)
}
AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span),
}
}
@ -3266,25 +3259,11 @@ impl<'a> LoweringContext<'a> {
// This is the normal case.
AnonymousLifetimeMode::PassThrough => {}
// We don't need to do any replacement here as this lifetime
// doesn't refer to an elided lifetime elsewhere in the function
// signature.
AnonymousLifetimeMode::Replace(_) => {}
}
self.new_implicit_lifetime(span)
}
fn new_replacement_lifetime(
&mut self,
replacement: LtReplacement,
span: Span,
) -> hir::Lifetime {
let hir_id = self.next_id();
self.replace_elided_lifetime(hir_id, span, replacement)
}
fn new_implicit_lifetime(&mut self, span: Span) -> hir::Lifetime {
hir::Lifetime {
hir_id: self.next_id(),

View File

@ -552,7 +552,7 @@ impl LoweringContext<'_> {
// let mut pinned = <expr>;
let expr = P(self.lower_expr(expr));
let pinned_ident = Ident::with_empty_ctxt(sym::pinned);
let pinned_ident = Ident::with_dummy_span(sym::pinned);
let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode(
span,
pinned_ident,
@ -593,7 +593,7 @@ impl LoweringContext<'_> {
let loop_node_id = self.sess.next_node_id();
let loop_hir_id = self.lower_node_id(loop_node_id);
let ready_arm = {
let x_ident = Ident::with_empty_ctxt(sym::result);
let x_ident = Ident::with_dummy_span(sym::result);
let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid));
let ready_pat = self.pat_std_enum(
@ -677,6 +677,7 @@ impl LoweringContext<'_> {
let fn_decl = self.lower_fn_decl(decl, None, false, None);
self.with_new_scopes(|this| {
let prev = this.current_item;
this.current_item = Some(fn_decl_span);
let mut generator_kind = None;
let body_id = this.lower_fn_body(decl, |this| {
@ -690,8 +691,10 @@ impl LoweringContext<'_> {
generator_kind,
movability,
);
let capture_clause = this.lower_capture_clause(capture_clause);
this.current_item = prev;
hir::ExprKind::Closure(
this.lower_capture_clause(capture_clause),
capture_clause,
fn_decl,
body_id,
fn_decl_span,
@ -981,7 +984,6 @@ impl LoweringContext<'_> {
volatile: asm.volatile,
alignstack: asm.alignstack,
dialect: asm.dialect,
ctxt: asm.ctxt,
};
let outputs = asm.outputs
@ -1067,9 +1069,9 @@ impl LoweringContext<'_> {
);
head.span = desugared_span;
let iter = Ident::with_empty_ctxt(sym::iter);
let iter = Ident::with_dummy_span(sym::iter);
let next_ident = Ident::with_empty_ctxt(sym::__next);
let next_ident = Ident::with_dummy_span(sym::__next);
let (next_pat, next_pat_hid) = self.pat_ident_binding_mode(
desugared_span,
next_ident,
@ -1078,7 +1080,7 @@ impl LoweringContext<'_> {
// `::std::option::Option::Some(val) => __next = val`
let pat_arm = {
let val_ident = Ident::with_empty_ctxt(sym::val);
let val_ident = Ident::with_dummy_span(sym::val);
let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident);
let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid));
let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid));
@ -1244,7 +1246,7 @@ impl LoweringContext<'_> {
// `Ok(val) => #[allow(unreachable_code)] val,`
let ok_arm = {
let val_ident = Ident::with_empty_ctxt(sym::val);
let val_ident = Ident::with_dummy_span(sym::val);
let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
let val_expr = P(self.expr_ident_with_attrs(
span,
@ -1260,7 +1262,7 @@ impl LoweringContext<'_> {
// `Err(err) => #[allow(unreachable_code)]
// return Try::from_error(From::from(err)),`
let err_arm = {
let err_ident = Ident::with_empty_ctxt(sym::err);
let err_ident = Ident::with_dummy_span(sym::err);
let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident);
let from_expr = {
let from_path = &[sym::convert, sym::From, sym::from];

View File

@ -60,10 +60,12 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> {
fn visit_item(&mut self, item: &'tcx Item) {
let mut item_hir_id = None;
self.lctx.with_hir_id_owner(item.id, |lctx| {
if let Some(hir_item) = lctx.lower_item(item) {
item_hir_id = Some(hir_item.hir_id);
lctx.insert_item(hir_item);
}
lctx.without_in_scope_lifetime_defs(|lctx| {
if let Some(hir_item) = lctx.lower_item(item) {
item_hir_id = Some(hir_item.hir_id);
lctx.insert_item(hir_item);
}
})
});
if let Some(hir_id) = item_hir_id {
@ -123,7 +125,7 @@ impl LoweringContext<'_> {
_ => &[],
};
let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind {
hir::GenericParamKind::Lifetime { .. } => Some(param.name.ident().modern()),
hir::GenericParamKind::Lifetime { .. } => Some(param.name.modern()),
_ => None,
});
self.in_scope_lifetimes.extend(lt_def_names);
@ -134,6 +136,28 @@ impl LoweringContext<'_> {
res
}
// Clears (and restores) the `in_scope_lifetimes` field. Used when
// visiting nested items, which never inherit in-scope lifetimes
// from their surrounding environment.
fn without_in_scope_lifetime_defs<T>(
&mut self,
f: impl FnOnce(&mut LoweringContext<'_>) -> T,
) -> T {
let old_in_scope_lifetimes = std::mem::replace(&mut self.in_scope_lifetimes, vec![]);
// this vector is only used when walking over impl headers,
// input types, and the like, and should not be non-empty in
// between items
assert!(self.lifetimes_to_define.is_empty());
let res = f(self);
assert!(self.in_scope_lifetimes.is_empty());
self.in_scope_lifetimes = old_in_scope_lifetimes;
res
}
pub(super) fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
hir::Mod {
inner: m.inner,
@ -726,21 +750,16 @@ impl LoweringContext<'_> {
}
fn lower_global_asm(&mut self, ga: &GlobalAsm) -> P<hir::GlobalAsm> {
P(hir::GlobalAsm {
asm: ga.asm,
ctxt: ga.ctxt,
})
P(hir::GlobalAsm { asm: ga.asm })
}
fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
Spanned {
node: hir::VariantKind {
ident: v.node.ident,
id: self.lower_node_id(v.node.id),
attrs: self.lower_attrs(&v.node.attrs),
data: self.lower_variant_data(&v.node.data),
disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
},
hir::Variant {
attrs: self.lower_attrs(&v.attrs),
data: self.lower_variant_data(&v.data),
disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
id: self.lower_node_id(v.id),
ident: v.ident,
span: v.span,
}
}

View File

@ -544,11 +544,11 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
}
fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: HirId) {
self.insert(v.span, v.node.id, Node::Variant(v));
self.with_parent(v.node.id, |this| {
self.insert(v.span, v.id, Node::Variant(v));
self.with_parent(v.id, |this| {
// Register the constructor of this variant.
if let Some(ctor_hir_id) = v.node.data.ctor_hir_id() {
this.insert(v.span, ctor_hir_id, Node::Ctor(&v.node.data));
if let Some(ctor_hir_id) = v.data.ctor_hir_id() {
this.insert(v.span, ctor_hir_id, Node::Ctor(&v.data));
}
intravisit::walk_variant(this, v, g, item_id);
});

View File

@ -155,11 +155,11 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
}
fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) {
let def = self.create_def(v.node.id,
DefPathData::TypeNs(v.node.ident.as_interned_str()),
let def = self.create_def(v.id,
DefPathData::TypeNs(v.ident.as_interned_str()),
v.span);
self.with_parent(def, |this| {
if let Some(ctor_hir_id) = v.node.data.ctor_id() {
if let Some(ctor_hir_id) = v.data.ctor_id() {
this.create_def(ctor_hir_id, DefPathData::Ctor, v.span);
}
visit::walk_variant(this, v, g, item_id)

View File

@ -649,12 +649,34 @@ impl<'hir> Map<'hir> {
}
}
pub fn is_const_scope(&self, hir_id: HirId) -> bool {
self.walk_parent_nodes(hir_id, |node| match *node {
Node::Item(Item { node: ItemKind::Const(_, _), .. }) => true,
Node::Item(Item { node: ItemKind::Fn(_, header, _, _), .. }) => header.is_const(),
/// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context.
/// Used exclusively for diagnostics, to avoid suggestion function calls.
pub fn is_const_context(&self, hir_id: HirId) -> bool {
let parent_id = self.get_parent_item(hir_id);
match self.get(parent_id) {
Node::Item(&Item {
node: ItemKind::Const(..),
..
})
| Node::TraitItem(&TraitItem {
node: TraitItemKind::Const(..),
..
})
| Node::ImplItem(&ImplItem {
node: ImplItemKind::Const(..),
..
})
| Node::AnonConst(_)
| Node::Item(&Item {
node: ItemKind::Static(..),
..
}) => true,
Node::Item(&Item {
node: ItemKind::Fn(_, header, ..),
..
}) => header.constness == Constness::Const,
_ => false,
}, |_| false).map(|id| id != CRATE_HIR_ID).unwrap_or(false)
}
}
/// If there is some error when walking the parents (e.g., a node does not
@ -885,7 +907,7 @@ impl<'hir> Map<'hir> {
_ => bug!("struct ID bound to non-struct {}", self.node_to_string(id))
}
}
Some(Node::Variant(variant)) => &variant.node.data,
Some(Node::Variant(variant)) => &variant.data,
Some(Node::Ctor(data)) => data,
_ => bug!("expected struct or variant, found {}", self.node_to_string(id))
}
@ -918,7 +940,7 @@ impl<'hir> Map<'hir> {
Node::ForeignItem(fi) => fi.ident.name,
Node::ImplItem(ii) => ii.ident.name,
Node::TraitItem(ti) => ti.ident.name,
Node::Variant(v) => v.node.ident.name,
Node::Variant(v) => v.ident.name,
Node::Field(f) => f.ident.name,
Node::Lifetime(lt) => lt.name.ident().name,
Node::GenericParam(param) => param.name.ident().name,
@ -939,7 +961,7 @@ impl<'hir> Map<'hir> {
Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]),
Some(Node::TraitItem(ref ti)) => Some(&ti.attrs[..]),
Some(Node::ImplItem(ref ii)) => Some(&ii.attrs[..]),
Some(Node::Variant(ref v)) => Some(&v.node.attrs[..]),
Some(Node::Variant(ref v)) => Some(&v.attrs[..]),
Some(Node::Field(ref f)) => Some(&f.attrs[..]),
Some(Node::Expr(ref e)) => Some(&*e.attrs),
Some(Node::Stmt(ref s)) => Some(s.node.attrs()),
@ -1133,7 +1155,7 @@ impl<T:Named> Named for Spanned<T> { fn name(&self) -> Name { self.node.name() }
impl Named for Item { fn name(&self) -> Name { self.ident.name } }
impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } }
impl Named for VariantKind { fn name(&self) -> Name { self.ident.name } }
impl Named for Variant { fn name(&self) -> Name { self.ident.name } }
impl Named for StructField { fn name(&self) -> Name { self.ident.name } }
impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } }
impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } }
@ -1310,7 +1332,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
}
Some(Node::Variant(ref variant)) => {
format!("variant {} in {}{}",
variant.node.ident,
variant.ident,
path_str(), id_str)
}
Some(Node::Field(ref field)) => {

View File

@ -23,7 +23,6 @@ use rustc_target::spec::abi::Abi;
use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy};
use syntax::attr::{InlineAttr, OptimizeAttr};
use syntax::ext::hygiene::SyntaxContext;
use syntax::symbol::{Symbol, kw};
use syntax::tokenstream::TokenStream;
use syntax::util::parser::ExprPrecedence;
@ -202,7 +201,7 @@ impl ParamName {
match *self {
ParamName::Plain(ident) => ident,
ParamName::Fresh(_) |
ParamName::Error => Ident::with_empty_ctxt(kw::UnderscoreLifetime),
ParamName::Error => Ident::with_dummy_span(kw::UnderscoreLifetime),
}
}
@ -237,8 +236,8 @@ impl LifetimeName {
pub fn ident(&self) -> Ident {
match *self {
LifetimeName::Implicit | LifetimeName::Error => Ident::invalid(),
LifetimeName::Underscore => Ident::with_empty_ctxt(kw::UnderscoreLifetime),
LifetimeName::Static => Ident::with_empty_ctxt(kw::StaticLifetime),
LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime),
LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime),
LifetimeName::Param(param_name) => param_name.ident(),
}
}
@ -877,7 +876,7 @@ impl Pat {
match self.node {
PatKind::Binding(.., Some(ref p)) => p.walk_(it),
PatKind::Struct(_, ref fields, _) => {
fields.iter().all(|field| field.node.pat.walk_(it))
fields.iter().all(|field| field.pat.walk_(it))
}
PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => {
s.iter().all(|p| p.walk_(it))
@ -923,6 +922,7 @@ pub struct FieldPat {
/// The pattern the field is destructured to.
pub pat: P<Pat>,
pub is_shorthand: bool,
pub span: Span,
}
/// Explicit binding annotations given in the HIR for a binding. Note
@ -968,7 +968,7 @@ pub enum PatKind {
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
/// The `bool` is `true` in the presence of a `..`.
Struct(QPath, HirVec<Spanned<FieldPat>>, bool),
Struct(QPath, HirVec<FieldPat>, bool),
/// A tuple struct/variant pattern `Variant(x, y, .., z)`.
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
@ -1541,7 +1541,7 @@ pub enum ExprKind {
Match(P<Expr>, HirVec<Arm>, MatchSource),
/// A closure (e.g., `move |a, b, c| {a + b + c}`).
///
/// The final span is the span of the argument block `|...|`.
/// The `Span` is the argument block `|...|`.
///
/// This may also be a generator literal or an `async block` as indicated by the
/// `Option<GeneratorMovability>`.
@ -2003,8 +2003,6 @@ pub struct InlineAsm {
pub volatile: bool,
pub alignstack: bool,
pub dialect: AsmDialect,
#[stable_hasher(ignore)] // This is used for error reporting
pub ctxt: SyntaxContext,
}
/// Represents an argument in a function header.
@ -2183,8 +2181,6 @@ pub struct ForeignMod {
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
pub struct GlobalAsm {
pub asm: Symbol,
#[stable_hasher(ignore)] // This is used for error reporting
pub ctxt: SyntaxContext,
}
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
@ -2193,7 +2189,7 @@ pub struct EnumDef {
}
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
pub struct VariantKind {
pub struct Variant {
/// Name of the variant.
#[stable_hasher(project(name))]
pub ident: Ident,
@ -2205,10 +2201,10 @@ pub struct VariantKind {
pub data: VariantData,
/// Explicit discriminant (e.g., `Foo = 1`).
pub disr_expr: Option<AnonConst>,
/// Span
pub span: Span
}
pub type Variant = Spanned<VariantKind>;
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)]
pub enum UseKind {
/// One import, e.g., `use foo::bar` or `use foo::bar as baz`.

View File

@ -737,7 +737,7 @@ impl<'a> State<'a> {
for v in variants {
self.space_if_not_bol();
self.maybe_print_comment(v.span.lo());
self.print_outer_attributes(&v.node.attrs);
self.print_outer_attributes(&v.attrs);
self.ibox(INDENT_UNIT);
self.print_variant(v);
self.s.word(",");
@ -829,8 +829,8 @@ impl<'a> State<'a> {
pub fn print_variant(&mut self, v: &hir::Variant) {
self.head("");
let generics = hir::Generics::empty();
self.print_struct(&v.node.data, &generics, v.node.ident.name, v.span, false);
if let Some(ref d) = v.node.disr_expr {
self.print_struct(&v.data, &generics, v.ident.name, v.span, false);
if let Some(ref d) = v.disr_expr {
self.s.space();
self.word_space("=");
self.print_anon_const(d);
@ -1457,7 +1457,7 @@ impl<'a> State<'a> {
}
pub fn print_name(&mut self, name: ast::Name) {
self.print_ident(ast::Ident::with_empty_ctxt(name))
self.print_ident(ast::Ident::with_dummy_span(name))
}
pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) {
@ -1670,14 +1670,14 @@ impl<'a> State<'a> {
&fields[..],
|s, f| {
s.cbox(INDENT_UNIT);
if !f.node.is_shorthand {
s.print_ident(f.node.ident);
if !f.is_shorthand {
s.print_ident(f.ident);
s.word_nbsp(":");
}
s.print_pat(&f.node.pat);
s.print_pat(&f.pat);
s.end()
},
|f| f.node.pat.span);
|f| f.pat.span);
if etc {
if !fields.is_empty() {
self.word_space(",");

View File

@ -350,7 +350,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for Span {
let line_col_len = col | line | len;
std_hash::Hash::hash(&line_col_len, hasher);
if span.ctxt == SyntaxContext::empty() {
if span.ctxt == SyntaxContext::root() {
TAG_NO_EXPANSION.hash_stable(hcx, hasher);
} else {
TAG_EXPANSION.hash_stable(hcx, hasher);
@ -370,7 +370,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for Span {
}
let mut hasher = StableHasher::new();
expn_id.expn_info().hash_stable(hcx, &mut hasher);
expn_id.expn_data().hash_stable(hcx, &mut hasher);
let sub_hash: Fingerprint = hasher.finish();
let sub_hash = sub_hash.to_smaller_hash();
cache.borrow_mut().insert(expn_id, sub_hash);

View File

@ -153,8 +153,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Ty {
}
}
impl_stable_hash_for_spanned!(hir::FieldPat);
impl_stable_hash_for_spanned!(hir::BinOpKind);
impl_stable_hash_for!(struct hir::Stmt {
@ -187,8 +185,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Expr {
impl_stable_hash_for_spanned!(usize);
impl_stable_hash_for_spanned!(ast::Ident);
impl_stable_hash_for!(struct ast::Ident {
name,
span,
@ -304,7 +300,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Mod {
}
}
impl_stable_hash_for_spanned!(hir::VariantKind);
impl_stable_hash_for_spanned!(hir::Variant);
impl<'a> HashStable<StableHashingContext<'a>> for hir::Item {

View File

@ -397,9 +397,10 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::Transparency {
Opaque,
});
impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
call_site,
impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnData {
kind,
parent -> _,
call_site,
def_site,
default_transparency,
allow_internal_unstable,

View File

@ -1,5 +1,5 @@
use crate::hir::def::Namespace;
use crate::hir::{self, Local, Pat, Body, HirId};
use crate::hir::{self, Body, FunctionRetTy, Expr, ExprKind, HirId, Local, Pat};
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
use crate::infer::InferCtxt;
use crate::infer::type_variable::TypeVariableOriginKind;
@ -7,7 +7,7 @@ use crate::ty::{self, Ty, Infer, TyVar};
use crate::ty::print::Print;
use syntax::source_map::DesugaringKind;
use syntax_pos::Span;
use errors::DiagnosticBuilder;
use errors::{Applicability, DiagnosticBuilder};
struct FindLocalByTypeVisitor<'a, 'tcx> {
infcx: &'a InferCtxt<'a, 'tcx>,
@ -16,9 +16,26 @@ struct FindLocalByTypeVisitor<'a, 'tcx> {
found_local_pattern: Option<&'tcx Pat>,
found_arg_pattern: Option<&'tcx Pat>,
found_ty: Option<Ty<'tcx>>,
found_closure: Option<&'tcx ExprKind>,
}
impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> {
fn new(
infcx: &'a InferCtxt<'a, 'tcx>,
target_ty: Ty<'tcx>,
hir_map: &'a hir::map::Map<'tcx>,
) -> Self {
Self {
infcx,
target_ty,
hir_map,
found_local_pattern: None,
found_arg_pattern: None,
found_ty: None,
found_closure: None,
}
}
fn node_matches_type(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> {
let ty_opt = self.infcx.in_progress_tables.and_then(|tables| {
tables.borrow().node_type_opt(hir_id)
@ -72,6 +89,60 @@ impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> {
}
intravisit::walk_body(self, body);
}
fn visit_expr(&mut self, expr: &'tcx Expr) {
if let (ExprKind::Closure(_, _fn_decl, _id, _sp, _), Some(_)) = (
&expr.node,
self.node_matches_type(expr.hir_id),
) {
self.found_closure = Some(&expr.node);
}
intravisit::walk_expr(self, expr);
}
}
/// Suggest giving an appropriate return type to a closure expression.
fn closure_return_type_suggestion(
span: Span,
err: &mut DiagnosticBuilder<'_>,
output: &FunctionRetTy,
body: &Body,
name: &str,
ret: &str,
) {
let (arrow, post) = match output {
FunctionRetTy::DefaultReturn(_) => ("-> ", " "),
_ => ("", ""),
};
let suggestion = match body.value.node {
ExprKind::Block(..) => {
vec![(output.span(), format!("{}{}{}", arrow, ret, post))]
}
_ => {
vec![
(output.span(), format!("{}{}{}{{ ", arrow, ret, post)),
(body.value.span.shrink_to_hi(), " }".to_string()),
]
}
};
err.multipart_suggestion(
"give this closure an explicit return type without `_` placeholders",
suggestion,
Applicability::HasPlaceholders,
);
err.span_label(span, InferCtxt::missing_type_msg(&name));
}
/// Given a closure signature, return a `String` containing a list of all its argument types.
fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String {
fn_sig.inputs()
.skip_binder()
.iter()
.next()
.map(|args| args.tuple_fields()
.map(|arg| arg.to_string())
.collect::<Vec<_>>().join(", "))
.unwrap_or_default()
}
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
@ -106,16 +177,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let ty = self.resolve_vars_if_possible(&ty);
let name = self.extract_type_name(&ty, None);
let mut err_span = span;
let mut local_visitor = FindLocalByTypeVisitor {
infcx: &self,
target_ty: ty,
hir_map: &self.tcx.hir(),
found_local_pattern: None,
found_arg_pattern: None,
found_ty: None,
};
let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, &self.tcx.hir());
let ty_to_string = |ty: Ty<'tcx>| -> String {
let mut s = String::new();
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
@ -136,6 +198,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let expr = self.tcx.hir().expect_expr(body_id.hir_id);
local_visitor.visit_expr(expr);
}
let err_span = if let Some(pattern) = local_visitor.found_arg_pattern {
pattern.span
} else {
span
};
let is_named_and_not_impl_trait = |ty: Ty<'_>| {
&ty.to_string() != "_" &&
// FIXME: Remove this check after `impl_trait_in_bindings` is stabilized. #63527
(!ty.is_impl_trait() || self.tcx.features().impl_trait_in_bindings)
};
let ty_msg = match local_visitor.found_ty {
Some(ty::TyS { sty: ty::Closure(def_id, substs), .. }) => {
let fn_sig = substs.closure_sig(*def_id, self.tcx);
let args = closure_args(&fn_sig);
let ret = fn_sig.output().skip_binder().to_string();
format!(" for the closure `fn({}) -> {}`", args, ret)
}
Some(ty) if is_named_and_not_impl_trait(ty) => {
let ty = ty_to_string(ty);
format!(" for `{}`", ty)
}
_ => String::new(),
};
// When `name` corresponds to a type argument, show the path of the full type we're
// trying to infer. In the following example, `ty_msg` contains
@ -150,27 +237,58 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// | consider giving `b` the explicit type `std::result::Result<i32, E>`, where
// | the type parameter `E` is specified
// ```
let (ty_msg, suffix) = match &local_visitor.found_ty {
Some(ty) if &ty.to_string() != "_" && name == "_" => {
let ty = ty_to_string(ty);
(format!(" for `{}`", ty),
format!("the explicit type `{}`, with the type parameters specified", ty))
let mut err = struct_span_err!(
self.tcx.sess,
err_span,
E0282,
"type annotations needed{}",
ty_msg,
);
let suffix = match local_visitor.found_ty {
Some(ty::TyS { sty: ty::Closure(def_id, substs), .. }) => {
let fn_sig = substs.closure_sig(*def_id, self.tcx);
let ret = fn_sig.output().skip_binder().to_string();
if let Some(ExprKind::Closure(_, decl, body_id, ..)) = local_visitor.found_closure {
if let Some(body) = self.tcx.hir().krate().bodies.get(body_id) {
closure_return_type_suggestion(
span,
&mut err,
&decl.output,
&body,
&name,
&ret,
);
// We don't want to give the other suggestions when the problem is the
// closure return type.
return err;
}
}
// This shouldn't be reachable, but just in case we leave a reasonable fallback.
let args = closure_args(&fn_sig);
// This suggestion is incomplete, as the user will get further type inference
// errors due to the `_` placeholders and the introduction of `Box`, but it does
// nudge them in the right direction.
format!("a boxed closure type like `Box<dyn Fn({}) -> {}>`", args, ret)
}
Some(ty) if &ty.to_string() != "_" && ty.to_string() != name => {
Some(ty) if is_named_and_not_impl_trait(ty) && name == "_" => {
let ty = ty_to_string(ty);
(format!(" for `{}`", ty),
format!(
"the explicit type `{}`, where the type parameter `{}` is specified",
format!("the explicit type `{}`, with the type parameters specified", ty)
}
Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != name => {
let ty = ty_to_string(ty);
format!(
"the explicit type `{}`, where the type parameter `{}` is specified",
ty,
name,
))
)
}
_ => (String::new(), "a type".to_owned()),
_ => "a type".to_string(),
};
let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))];
if let Some(pattern) = local_visitor.found_arg_pattern {
err_span = pattern.span;
// We don't want to show the default label for closures.
//
// So, before clearing, the output would look something like this:
@ -187,39 +305,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// ^ consider giving this closure parameter the type `[_; 0]`
// with the type parameter `_` specified
// ```
labels.clear();
labels.push((
err.span_label(
pattern.span,
format!("consider giving this closure parameter {}", suffix),
));
);
} else if let Some(pattern) = local_visitor.found_local_pattern {
if let Some(simple_ident) = pattern.simple_ident() {
let msg = if let Some(simple_ident) = pattern.simple_ident() {
match pattern.span.desugaring_kind() {
None => labels.push((
pattern.span,
format!("consider giving `{}` {}", simple_ident, suffix),
)),
Some(DesugaringKind::ForLoop) => labels.push((
pattern.span,
"the element type for this iterator is not specified".to_owned(),
)),
_ => {}
None => {
format!("consider giving `{}` {}", simple_ident, suffix)
}
Some(DesugaringKind::ForLoop) => {
"the element type for this iterator is not specified".to_string()
}
_ => format!("this needs {}", suffix),
}
} else {
labels.push((pattern.span, format!("consider giving this pattern {}", suffix)));
}
};
let mut err = struct_span_err!(
self.tcx.sess,
err_span,
E0282,
"type annotations needed{}",
ty_msg,
);
for (target_span, label_message) in labels {
err.span_label(target_span, label_message);
format!("consider giving this pattern {}", suffix)
};
err.span_label(pattern.span, msg);
}
if !err.span.span_labels().iter().any(|span_label| {
span_label.label.is_some() && span_label.span == span
}) && local_visitor.found_arg_pattern.is_none()
{ // Avoid multiple labels pointing at `span`.
err.span_label(span, InferCtxt::missing_type_msg(&name));
}
err

View File

@ -1060,7 +1060,7 @@ for LateContextAndPass<'a, 'tcx, T> {
v: &'tcx hir::Variant,
g: &'tcx hir::Generics,
item_id: hir::HirId) {
self.with_lint_attrs(v.node.id, &v.node.attrs, |cx| {
self.with_lint_attrs(v.id, &v.attrs, |cx| {
lint_callback!(cx, check_variant, v, g);
hir_visit::walk_variant(cx, v, g, item_id);
lint_callback!(cx, check_variant_post, v, g);
@ -1236,7 +1236,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
}
fn visit_variant(&mut self, v: &'a ast::Variant, g: &'a ast::Generics, item_id: ast::NodeId) {
self.with_lint_attrs(item_id, &v.node.attrs, |cx| {
self.with_lint_attrs(item_id, &v.attrs, |cx| {
run_early_pass!(cx, check_variant, v, g);
ast_visit::walk_variant(cx, v, g, item_id);
run_early_pass!(cx, check_variant_post, v, g);
@ -1345,7 +1345,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
// part of `walk_mac`, and (b) we should be calling
// `visit_path`, *but* that would require a `NodeId`, and I
// want to get #53686 fixed quickly. -nmatsakis
ast_visit::walk_path(self, &mac.node.path);
ast_visit::walk_path(self, &mac.path);
run_early_pass!(self, check_mac, mac);
}
@ -1355,7 +1355,7 @@ struct LateLintPassObjects<'a> {
lints: &'a mut [LateLintPassObject],
}
#[cfg_attr(not(bootstrap), allow(rustc::lint_pass_impl_without_macro))]
#[allow(rustc::lint_pass_impl_without_macro)]
impl LintPass for LateLintPassObjects<'_> {
fn name(&self) -> &'static str {
panic!()
@ -1525,7 +1525,7 @@ struct EarlyLintPassObjects<'a> {
lints: &'a mut [EarlyLintPassObject],
}
#[cfg_attr(not(bootstrap), allow(rustc::lint_pass_impl_without_macro))]
#[allow(rustc::lint_pass_impl_without_macro)]
impl LintPass for EarlyLintPassObjects<'_> {
fn name(&self) -> &'static str {
panic!()

View File

@ -9,7 +9,6 @@ use errors::Applicability;
use rustc_data_structures::fx::FxHashMap;
use syntax::ast::{Ident, Item, ItemKind};
use syntax::symbol::{sym, Symbol};
use syntax_pos::ExpnInfo;
declare_tool_lint! {
pub rustc::DEFAULT_HASH_TYPES,
@ -23,7 +22,7 @@ pub struct DefaultHashTypes {
impl DefaultHashTypes {
// we are allowed to use `HashMap` and `HashSet` as identifiers for implementing the lint itself
#[cfg_attr(not(bootstrap), allow(rustc::default_hash_types))]
#[allow(rustc::default_hash_types)]
pub fn new() -> Self {
let mut map = FxHashMap::default();
map.insert(sym::HashMap, sym::FxHashMap);
@ -108,7 +107,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind {
.help("try using `Ty` instead")
.emit();
} else {
if ty.span.ctxt().outer_expn_info().is_some() {
if ty.span.from_expansion() {
return;
}
if let Some(t) = is_ty_or_ty_ctxt(cx, ty) {
@ -228,30 +227,20 @@ impl EarlyLintPass for LintPassImpl {
if let ItemKind::Impl(_, _, _, _, Some(lint_pass), _, _) = &item.node {
if let Some(last) = lint_pass.path.segments.last() {
if last.ident.name == sym::LintPass {
match &lint_pass.path.span.ctxt().outer_expn_info() {
Some(info) if is_lint_pass_expansion(info) => {}
_ => {
cx.struct_span_lint(
LINT_PASS_IMPL_WITHOUT_MACRO,
lint_pass.path.span,
"implementing `LintPass` by hand",
)
.help("try using `declare_lint_pass!` or `impl_lint_pass!` instead")
.emit();
}
let expn_data = lint_pass.path.span.ctxt().outer_expn_data();
let call_site = expn_data.call_site;
if expn_data.kind.descr() != sym::impl_lint_pass &&
call_site.ctxt().outer_expn_data().kind.descr() != sym::declare_lint_pass {
cx.struct_span_lint(
LINT_PASS_IMPL_WITHOUT_MACRO,
lint_pass.path.span,
"implementing `LintPass` by hand",
)
.help("try using `declare_lint_pass!` or `impl_lint_pass!` instead")
.emit();
}
}
}
}
}
}
fn is_lint_pass_expansion(expn_info: &ExpnInfo) -> bool {
if expn_info.kind.descr() == sym::impl_lint_pass {
true
} else if let Some(info) = expn_info.call_site.ctxt().outer_expn_info() {
info.kind.descr() == sym::declare_lint_pass
} else {
false
}
}

View File

@ -846,7 +846,7 @@ impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> {
v: &'tcx hir::Variant,
g: &'tcx hir::Generics,
item_id: hir::HirId) {
self.with_lint_attrs(v.node.id, &v.node.attrs, |builder| {
self.with_lint_attrs(v.id, &v.attrs, |builder| {
intravisit::walk_variant(builder, v, g, item_id);
})
}
@ -885,21 +885,16 @@ pub fn provide(providers: &mut Providers<'_>) {
/// This is used to test whether a lint should not even begin to figure out whether it should
/// be reported on the current node.
pub fn in_external_macro(sess: &Session, span: Span) -> bool {
let info = match span.ctxt().outer_expn_info() {
Some(info) => info,
// no ExpnInfo means this span doesn't come from a macro
None => return false,
};
match info.kind {
let expn_data = span.ctxt().outer_expn_data();
match expn_data.kind {
ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
ExpnKind::Desugaring(_) => true, // well, it's "external"
ExpnKind::Macro(MacroKind::Bang, _) => {
if info.def_site.is_dummy() {
if expn_data.def_site.is_dummy() {
// dummy span for the def_site means it's an external macro
return true;
}
match sess.source_map().span_to_snippet(info.def_site) {
match sess.source_map().span_to_snippet(expn_data.def_site) {
Ok(code) => !code.starts_with("macro_rules"),
// no snippet = external macro or compiler-builtin expansion
Err(_) => true,
@ -911,10 +906,8 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
/// Returns whether `span` originates in a derive macro's expansion
pub fn in_derive_expansion(span: Span) -> bool {
if let Some(info) = span.ctxt().outer_expn_info() {
if let ExpnKind::Macro(MacroKind::Derive, _) = info.kind {
return true;
}
if let ExpnKind::Macro(MacroKind::Derive, _) = span.ctxt().outer_expn_data().kind {
return true;
}
false
}

View File

@ -178,8 +178,7 @@ pub trait MetadataLoader {
-> Result<MetadataRef, String>;
}
/// A store of Rust crates, through with their metadata
/// can be accessed.
/// A store of Rust crates, through which their metadata can be accessed.
///
/// Note that this trait should probably not be expanding today. All new
/// functionality should be driven through queries instead!

View File

@ -17,8 +17,7 @@ use crate::util::nodemap::FxHashSet;
use rustc_data_structures::fx::FxHashMap;
use syntax::{ast, source_map};
use syntax::attr;
use syntax::{ast, attr};
use syntax::symbol::sym;
use syntax_pos;
@ -119,17 +118,16 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
}
}
fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, res: Res,
pats: &[source_map::Spanned<hir::FieldPat>]) {
fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, res: Res, pats: &[hir::FieldPat]) {
let variant = match self.tables.node_type(lhs.hir_id).sty {
ty::Adt(adt, _) => adt.variant_of_res(res),
_ => span_bug!(lhs.span, "non-ADT in struct pattern")
};
for pat in pats {
if let PatKind::Wild = pat.node.pat.node {
if let PatKind::Wild = pat.pat.node {
continue;
}
let index = self.tcx.field_index(pat.node.hir_id, self.tables);
let index = self.tcx.field_index(pat.hir_id, self.tables);
self.insert_def_id(variant.fields[index].did);
}
}
@ -366,12 +364,12 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
match item.node {
hir::ItemKind::Enum(ref enum_def, _) => {
if allow_dead_code {
self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id));
self.worklist.extend(enum_def.variants.iter().map(|variant| variant.id));
}
for variant in &enum_def.variants {
if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() {
self.struct_constructors.insert(ctor_hir_id, variant.node.id);
if let Some(ctor_hir_id) = variant.data.ctor_hir_id() {
self.struct_constructors.insert(ctor_hir_id, variant.id);
}
}
}
@ -497,7 +495,7 @@ impl DeadVisitor<'tcx> {
&& !has_allow_dead_code_or_lang_attr(self.tcx, field.hir_id, &field.attrs)
}
fn should_warn_about_variant(&mut self, variant: &hir::VariantKind) -> bool {
fn should_warn_about_variant(&mut self, variant: &hir::Variant) -> bool {
!self.symbol_is_live(variant.id)
&& !has_allow_dead_code_or_lang_attr(self.tcx,
variant.id,
@ -596,8 +594,8 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
variant: &'tcx hir::Variant,
g: &'tcx hir::Generics,
id: hir::HirId) {
if self.should_warn_about_variant(&variant.node) {
self.warn_dead_code(variant.node.id, variant.span, variant.node.ident.name,
if self.should_warn_about_variant(&variant) {
self.warn_dead_code(variant.id, variant.span, variant.ident.name,
"variant", "constructed");
} else {
intravisit::walk_variant(self, variant, g, id);

View File

@ -418,8 +418,8 @@ fn add_from_pat<'tcx>(ir: &mut IrMaps<'tcx>, pat: &P<hir::Pat>) {
}
Struct(_, ref fields, _) => {
for field in fields {
if field.node.is_shorthand {
shorthand_field_ids.insert(field.node.pat.hir_id);
if field.is_shorthand {
shorthand_field_ids.insert(field.pat.hir_id);
}
}
}

View File

@ -1282,11 +1282,11 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
};
for fp in field_pats {
let field_ty = self.pat_ty_adjusted(&fp.node.pat)?; // see (*2)
let f_index = self.tcx.field_index(fp.node.hir_id, self.tables);
let field_ty = self.pat_ty_adjusted(&fp.pat)?; // see (*2)
let f_index = self.tcx.field_index(fp.hir_id, self.tables);
let cmt_field = Rc::new(self.cat_field(pat, cmt.clone(), f_index,
fp.node.ident, field_ty));
self.cat_pattern_(cmt_field, &fp.node.pat, op)?;
fp.ident, field_ty));
self.cat_pattern_(cmt_field, &fp.pat, op)?;
}
}

View File

@ -33,6 +33,9 @@ fn item_might_be_inlined(tcx: TyCtxt<'tcx>, item: &hir::Item, attrs: CodegenFnAt
}
match item.node {
hir::ItemKind::Fn(_, header, ..) if header.is_const() => {
return true;
}
hir::ItemKind::Impl(..) |
hir::ItemKind::Fn(..) => {
let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id));
@ -52,6 +55,11 @@ fn method_might_be_inlined(
if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) {
return true
}
if let hir::ImplItemKind::Method(method_sig, _) = &impl_item.node {
if method_sig.header.is_const() {
return true
}
}
if let Some(impl_hir_id) = tcx.hir().as_local_hir_id(impl_src) {
match tcx.hir().find(impl_hir_id) {
Some(Node::Item(item)) =>

View File

@ -1207,7 +1207,7 @@ fn resolve_local<'tcx>(
PatKind::Binding(hir::BindingAnnotation::RefMut, ..) => true,
PatKind::Struct(_, ref field_pats, _) => {
field_pats.iter().any(|fp| is_binding_pat(&fp.node.pat))
field_pats.iter().any(|fp| is_binding_pat(&fp.pat))
}
PatKind::Slice(ref pats1, ref pats2, ref pats3) => {

View File

@ -290,10 +290,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
}
fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) {
self.annotate(var.node.id, &var.node.attrs, var.span, AnnotationKind::Required,
self.annotate(var.id, &var.attrs, var.span, AnnotationKind::Required,
|v| {
if let Some(ctor_hir_id) = var.node.data.ctor_hir_id() {
v.annotate(ctor_hir_id, &var.node.attrs, var.span, AnnotationKind::Required,
if let Some(ctor_hir_id) = var.data.ctor_hir_id() {
v.annotate(ctor_hir_id, &var.attrs, var.span, AnnotationKind::Required,
|_| {});
}
@ -372,7 +372,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
}
fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) {
self.check_missing_stability(var.node.id, var.span, "variant");
self.check_missing_stability(var.id, var.span, "variant");
intravisit::walk_variant(self, var, g, item_id);
}

View File

@ -189,8 +189,11 @@ impl<'tcx, Tag> Pointer<Tag> {
Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () }
}
/// Test if the pointer is "inbounds" of an allocation of the given size.
/// A pointer is "inbounds" even if its offset is equal to the size; this is
/// a "one-past-the-end" pointer.
#[inline(always)]
pub fn check_in_alloc(
pub fn check_inbounds_alloc(
self,
allocation_size: Size,
msg: CheckInAllocMsg,

View File

@ -2197,7 +2197,6 @@ impl<'tcx> Operand<'tcx> {
let ty = tcx.type_of(def_id).subst(tcx, substs);
Operand::Constant(box Constant {
span,
ty,
user_ty: None,
literal: ty::Const::zero_sized(tcx, ty),
})
@ -2476,7 +2475,6 @@ impl<'tcx> Debug for Rvalue<'tcx> {
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
pub struct Constant<'tcx> {
pub span: Span,
pub ty: Ty<'tcx>,
/// Optional user-given type: for something like
/// `collect::<Vec<_>>`, this would be present and would
@ -3385,12 +3383,11 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
Constant {
span: self.span.clone(),
ty: self.ty.fold_with(folder),
user_ty: self.user_ty.fold_with(folder),
literal: self.literal.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.ty.visit_with(visitor) || self.literal.visit_with(visitor)
self.literal.visit_with(visitor)
}
}

View File

@ -252,7 +252,7 @@ impl<'tcx> Operand<'tcx> {
match self {
&Operand::Copy(ref l) |
&Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
&Operand::Constant(ref c) => c.ty,
&Operand::Constant(ref c) => c.literal.ty,
}
}
}

View File

@ -782,13 +782,11 @@ macro_rules! make_mir_visitor {
location: Location) {
let Constant {
span,
ty,
user_ty,
literal,
} = constant;
self.visit_span(span);
self.visit_ty(ty, TyContext::Location(location));
drop(user_ty); // no visit method for this
self.visit_const(literal, location);
}

View File

@ -395,7 +395,7 @@ top_level_options!(
output_types: OutputTypes [TRACKED],
search_paths: Vec<SearchPath> [UNTRACKED],
libs: Vec<(String, Option<String>, Option<cstore::NativeLibraryKind>)> [TRACKED],
maybe_sysroot: Option<PathBuf> [TRACKED],
maybe_sysroot: Option<PathBuf> [UNTRACKED],
target_triple: TargetTriple [TRACKED],

View File

@ -36,7 +36,7 @@ use errors::{Applicability, DiagnosticBuilder};
use std::fmt;
use syntax::ast;
use syntax::symbol::sym;
use syntax_pos::{DUMMY_SP, Span, ExpnInfo, ExpnKind};
use syntax_pos::{DUMMY_SP, Span, ExpnKind};
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn report_fulfillment_errors(&self,
@ -61,9 +61,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// We want to ignore desugarings here: spans are equivalent even
// if one is the result of a desugaring and the other is not.
let mut span = error.obligation.cause.span;
if let Some(ExpnInfo { kind: ExpnKind::Desugaring(_), def_site, .. })
= span.ctxt().outer_expn_info() {
span = def_site;
let expn_data = span.ctxt().outer_expn_data();
if let ExpnKind::Desugaring(_) = expn_data.kind {
span = expn_data.call_site;
}
error_map.entry(span).or_default().push(

View File

@ -1417,7 +1417,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
projection_ty: ty::ProjectionTy::from_ref_and_name(
tcx,
trait_ref,
Ident::with_empty_ctxt(FN_OUTPUT_NAME),
Ident::with_dummy_span(FN_OUTPUT_NAME),
),
ty: ret_type
}

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