[submodule "src/rt/hoedown"]
path = src/rt/hoedown
url = https://github.com/rust-lang/hoedown.git
+ branch = rust-2015-09-21-do-not-delete
[submodule "src/jemalloc"]
path = src/jemalloc
url = https://github.com/rust-lang/jemalloc.git
Paul Faria <paul_faria@ultimatesoftware.com> Paul Faria <Nashenas88@gmail.com>
Peer Aramillo Irizar <peer.aramillo.irizar@gmail.com> parir <peer.aramillo.irizar@gmail.com>
Peter Elmers <peter.elmers@yahoo.com> <peter.elmers@rice.edu>
+Peter Liniker <peter.liniker+github@gmail.com>
Peter Zotov <whitequark@whitequark.org>
Phil Dawes <phil@phildawes.net> Phil Dawes <pdawes@drw.com>
Philipp Brüschweiler <blei42@gmail.com> <blei42@gmail.com>
include:
# Linux builders, all docker images
- env: IMAGE=android DEPLOY=1
+ - env: IMAGE=armhf-gnu
- env: IMAGE=cross DEPLOY=1
- env: IMAGE=linux-tested-targets DEPLOY=1
- env: IMAGE=dist-arm-linux DEPLOY=1
before_deploy:
- mkdir -p deploy/$TRAVIS_COMMIT
- - rm -rf build/dist/doc
- >
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
+ rm -rf build/dist/doc &&
cp -r build/dist/* deploy/$TRAVIS_COMMIT;
else
+ rm -rf obj/build/dist/doc &&
cp -r obj/build/dist/* deploy/$TRAVIS_COMMIT;
fi
+Version 1.15.1 (2017-02-07)
+===========================
+
+* [Fix IntoIter::as_mut_slice's signature][39466]
+
+[39466]: https://github.com/rust-lang/rust/pull/39466
+
+
Version 1.15.0 (2017-02-02)
===========================
CFG_OSTYPE="${CFG_OSTYPE}eabihf"
;;
- aarch64)
+ aarch64 | arm64)
CFG_CPUTYPE=aarch64
;;
valopt musl-root-armhf "" "arm-unknown-linux-musleabihf install directory"
valopt musl-root-armv7 "" "armv7-unknown-linux-musleabihf install directory"
valopt extra-filename "" "Additional data that is hashed and passed to the -C extra-filename flag"
+valopt qemu-armhf-rootfs "" "rootfs in qemu testing, you probably don't want to use this"
if [ -e ${CFG_SRC_DIR}.git ]
then
--- /dev/null
+# rustbuild-only target
compiler_builtins core alloc \
std_unicode rustc_bitflags \
alloc_system alloc_jemalloc \
- panic_abort panic_unwind unwind rustc_i128
+ panic_abort panic_unwind unwind
RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_driver \
rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \
rustc_data_structures rustc_platform_intrinsics rustc_errors \
DEPS_graphviz := std
DEPS_log := std
DEPS_num := std
-DEPS_serialize := std log rustc_i128
+DEPS_serialize := std log
DEPS_term := std
DEPS_test := std getopts term native:rust_test_helpers
-DEPS_rustc_i128 = std
DEPS_syntax := std term serialize log arena libc rustc_bitflags std_unicode rustc_errors \
- syntax_pos rustc_data_structures rustc_i128
+ syntax_pos rustc_data_structures
DEPS_syntax_ext := syntax syntax_pos rustc_errors fmt_macros proc_macro
DEPS_proc_macro := syntax syntax_pos rustc_plugin log
DEPS_syntax_pos := serialize
DEPS_proc_macro_plugin := syntax syntax_pos rustc_plugin
-DEPS_rustc_const_math := std syntax log serialize rustc_i128
+DEPS_rustc_const_math := std syntax log serialize
DEPS_rustc_const_eval := rustc_const_math rustc syntax log serialize \
- rustc_back graphviz syntax_pos rustc_i128
+ rustc_back graphviz syntax_pos
DEPS_rustc := syntax fmt_macros flate arena serialize getopts \
log graphviz rustc_llvm rustc_back rustc_data_structures\
- rustc_const_math syntax_pos rustc_errors rustc_i128
+ rustc_const_math syntax_pos rustc_errors
DEPS_rustc_back := std syntax flate log libc
DEPS_rustc_borrowck := rustc log graphviz syntax syntax_pos rustc_errors rustc_mir
DEPS_rustc_data_structures := std log serialize libc
rustc_passes rustc_save_analysis rustc_const_eval \
rustc_incremental syntax_pos rustc_errors proc_macro rustc_data_structures
DEPS_rustc_errors := log libc serialize syntax_pos
-DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval rustc_i128
+DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval
DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
DEPS_proc_macro := std syntax
DEPS_rustc_metadata := rustc syntax syntax_pos rustc_errors rustc_const_math \
- proc_macro syntax_ext rustc_i128
+ proc_macro syntax_ext
DEPS_rustc_passes := syntax syntax_pos rustc core rustc_const_eval rustc_errors
-DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags \
- rustc_i128
+DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags
DEPS_rustc_resolve := arena rustc log syntax syntax_pos rustc_errors
DEPS_rustc_platform_intrinsics := std
DEPS_rustc_plugin := rustc rustc_metadata syntax syntax_pos rustc_errors
DEPS_rustc_privacy := rustc log syntax syntax_pos
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
- log syntax serialize rustc_llvm rustc_platform_intrinsics rustc_i128 \
+ log syntax serialize rustc_llvm rustc_platform_intrinsics \
rustc_const_math rustc_const_eval rustc_incremental rustc_errors syntax_pos
DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures
DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize
ONLY_RLIB_rand := 1
ONLY_RLIB_collections := 1
ONLY_RLIB_std_unicode := 1
-ONLY_RLIB_rustc_i128 := 1
ONLY_RLIB_rustc_bitflags := 1
ONLY_RLIB_alloc_system := 1
ONLY_RLIB_alloc_jemalloc := 1
######################################################################
# The version number
-CFG_RELEASE_NUM=1.16.0
+CFG_RELEASE_NUM=1.17.0
# An optional number to put after the label, e.g. '.2' -> '-beta.2'
# NB Make sure it starts with a dot to conform to semver pre-release
ifeq ($$(findstring msvc,$(1)),)
ifeq ($$(findstring freebsd,$(1)),)
+ifeq ($$(findstring netbsd,$(1)),)
$(call ADD_INTRINSIC,$(1),gcc_personality_v0.o)
endif
endif
+endif
ifeq ($$(findstring aarch64,$(1)),aarch64)
$(foreach intrinsic,comparetf2.o \
[[package]]
name = "build_helper"
version = "0.1.0"
+dependencies = [
+ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+]
[[package]]
name = "cargotest"
"syntax_pos 0.0.0",
]
+[[package]]
+name = "qemu-test-client"
+version = "0.1.0"
+
+[[package]]
+name = "qemu-test-server"
+version = "0.1.0"
+
[[package]]
name = "rand"
version = "0.0.0"
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
- "rustc_i128 0.0.0",
"rustc_llvm 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
- "rustc_i128 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
name = "rustc_const_math"
version = "0.0.0"
dependencies = [
- "rustc_i128 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
]
version = "0.0.0"
dependencies = [
"log 0.0.0",
- "rustc_i128 0.0.0",
"serialize 0.0.0",
]
name = "rustc_errors"
version = "0.0.0"
dependencies = [
+ "serialize 0.0.0",
"syntax_pos 0.0.0",
]
-[[package]]
-name = "rustc_i128"
-version = "0.0.0"
-
[[package]]
name = "rustc_incremental"
version = "0.0.0"
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_const_eval 0.0.0",
- "rustc_i128 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
- "rustc_i128 0.0.0",
"rustc_llvm 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"rustc_const_eval 0.0.0",
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
- "rustc_i128 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
- "rustc_i128 0.0.0",
"rustc_incremental 0.0.0",
"rustc_llvm 0.0.0",
"rustc_platform_intrinsics 0.0.0",
[[package]]
name = "serialize"
version = "0.0.0"
-dependencies = [
- "rustc_i128 0.0.0",
-]
[[package]]
name = "std"
[[package]]
name = "std_shim"
-version = "0.1.0"
+version = "0.0.0"
dependencies = [
"core 0.0.0",
"std 0.0.0",
"rustc_bitflags 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
- "rustc_i128 0.0.0",
"serialize 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "test_shim"
-version = "0.1.0"
+version = "0.0.0"
dependencies = [
"test 0.0.0",
]
"tools/rustbook",
"tools/tidy",
"tools/build-manifest",
+ "tools/qemu-test-client",
+ "tools/qemu-test-server",
]
# Curiously, compiletest will segfault if compiled with opt-level=3 on 64-bit
//! rustbuild, the Rust build system
//!
//! This is the entry point for the build system used to compile the `rustc`
-//! compiler. Lots of documentation can be found in the `README.md` file next to
-//! this file, and otherwise documentation can be found throughout the `build`
+//! compiler. Lots of documentation can be found in the `README.md` file in the
+//! parent directory, and otherwise documentation can be found throughout the `build`
//! directory in each respective module.
#![deny(warnings)]
ostype += 'eabihf'
elif cputype == 'aarch64':
cputype = 'aarch64'
+ elif cputype == 'arm64':
+ cputype = 'aarch64'
elif cputype == 'mips':
if sys.byteorder == 'big':
cputype = 'mips'
rb.use_vendored_sources = '\nvendor = true' in rb.config_toml or \
'CFG_ENABLE_VENDOR' in rb.config_mk
- if 'SUDO_USER' in os.environ:
- if os.environ['USER'] != os.environ['SUDO_USER']:
+ if 'SUDO_USER' in os.environ and not rb.use_vendored_sources:
+ if os.environ.get('USER') != os.environ['SUDO_USER']:
rb.use_vendored_sources = True
print('info: looks like you are running this command under `sudo`')
print(' and so in order to preserve your $HOME this will now')
print(' use vendored sources by default. Note that if this')
print(' does not work you should run a normal build first')
- print(' before running a command like `sudo make intall`')
+ print(' before running a command like `sudo make install`')
if rb.use_vendored_sources:
if not os.path.exists('.cargo'):
use {Build, Compiler, Mode};
use dist;
-use util::{self, dylib_path, dylib_path_var};
+use util::{self, dylib_path, dylib_path_var, exe};
const ADB_TEST_DIR: &'static str = "/data/tmp";
.arg("--llvm-cxxflags").arg("");
}
+ if build.qemu_rootfs(target).is_some() {
+ cmd.arg("--qemu-test-client")
+ .arg(build.tool(&Compiler::new(0, &build.config.build),
+ "qemu-test-client"));
+ }
+
// Running a C compiler on MSVC requires a few env vars to be set, to be
// sure to set them here.
//
// helper crate, not tested. If it leaks through then it ends up
// messing with various mtime calculations and such.
if !name.contains("jemalloc") && name != "build_helper" {
- cargo.arg("-p").arg(name);
+ cargo.arg("-p").arg(&format!("{}:0.0.0", name));
}
for dep in build.crates[name].deps.iter() {
if visited.insert(dep) {
dylib_path.insert(0, build.sysroot_libdir(&compiler, target));
cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
- if target.contains("android") {
- cargo.arg("--no-run");
- } else if target.contains("emscripten") {
+ if target.contains("android") ||
+ target.contains("emscripten") ||
+ build.qemu_rootfs(target).is_some() {
cargo.arg("--no-run");
}
} else if target.contains("emscripten") {
build.run(&mut cargo);
krate_emscripten(build, &compiler, target, mode);
+ } else if build.qemu_rootfs(target).is_some() {
+ build.run(&mut cargo);
+ krate_qemu(build, &compiler, target, mode);
} else {
cargo.args(&build.flags.cmd.test_args());
build.run(&mut cargo);
compiler: &Compiler,
target: &str,
mode: Mode) {
- let mut tests = Vec::new();
- let out_dir = build.cargo_out(compiler, mode, target);
- find_tests(&out_dir, target, &mut tests);
- find_tests(&out_dir.join("deps"), target, &mut tests);
-
- for test in tests {
- let test_file_name = test.to_string_lossy().into_owned();
- println!("running {}", test_file_name);
- let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured");
- let mut cmd = Command::new(nodejs);
- cmd.arg(&test_file_name);
- if build.config.quiet_tests {
- cmd.arg("--quiet");
- }
- build.run(&mut cmd);
- }
- }
+ let mut tests = Vec::new();
+ let out_dir = build.cargo_out(compiler, mode, target);
+ find_tests(&out_dir, target, &mut tests);
+ find_tests(&out_dir.join("deps"), target, &mut tests);
+
+ for test in tests {
+ let test_file_name = test.to_string_lossy().into_owned();
+ println!("running {}", test_file_name);
+ let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured");
+ let mut cmd = Command::new(nodejs);
+ cmd.arg(&test_file_name);
+ if build.config.quiet_tests {
+ cmd.arg("--quiet");
+ }
+ build.run(&mut cmd);
+ }
+}
+
+fn krate_qemu(build: &Build,
+ compiler: &Compiler,
+ target: &str,
+ mode: Mode) {
+ let mut tests = Vec::new();
+ let out_dir = build.cargo_out(compiler, mode, target);
+ find_tests(&out_dir, target, &mut tests);
+ find_tests(&out_dir.join("deps"), target, &mut tests);
+
+ let tool = build.tool(&Compiler::new(0, &build.config.build),
+ "qemu-test-client");
+ for test in tests {
+ let mut cmd = Command::new(&tool);
+ cmd.arg("run")
+ .arg(&test);
+ if build.config.quiet_tests {
+ cmd.arg("--quiet");
+ }
+ cmd.args(&build.flags.cmd.test_args());
+ build.run(&mut cmd);
+ }
+}
fn find_tests(dir: &Path,
}
}
-pub fn android_copy_libs(build: &Build,
- compiler: &Compiler,
- target: &str) {
- if !target.contains("android") {
- return
+pub fn emulator_copy_libs(build: &Build, compiler: &Compiler, target: &str) {
+ if target.contains("android") {
+ android_copy_libs(build, compiler, target)
+ } else if let Some(s) = build.qemu_rootfs(target) {
+ qemu_copy_libs(build, compiler, target, s)
}
+}
+fn android_copy_libs(build: &Build, compiler: &Compiler, target: &str) {
println!("Android copy libs to emulator ({})", target);
build.run(Command::new("adb").arg("wait-for-device"));
build.run(Command::new("adb").arg("remount"));
}
}
+fn qemu_copy_libs(build: &Build,
+ compiler: &Compiler,
+ target: &str,
+ rootfs: &Path) {
+ println!("QEMU copy libs to emulator ({})", target);
+ assert!(target.starts_with("arm"), "only works with arm for now");
+ t!(fs::create_dir_all(build.out.join("tmp")));
+
+ // Copy our freshly compiled test server over to the rootfs
+ let server = build.cargo_out(compiler, Mode::Tool, target)
+ .join(exe("qemu-test-server", target));
+ t!(fs::copy(&server, rootfs.join("testd")));
+
+ // Spawn the emulator and wait for it to come online
+ let tool = build.tool(&Compiler::new(0, &build.config.build),
+ "qemu-test-client");
+ build.run(Command::new(&tool)
+ .arg("spawn-emulator")
+ .arg(rootfs)
+ .arg(build.out.join("tmp")));
+
+ // Push all our dylibs to the emulator
+ for f in t!(build.sysroot_libdir(compiler, target).read_dir()) {
+ let f = t!(f);
+ let name = f.file_name().into_string().unwrap();
+ if util::is_dylib(&name) {
+ build.run(Command::new(&tool)
+ .arg("push")
+ .arg(f.path()));
+ }
+ }
+}
+
/// Run "distcheck", a 'make check' from a tarball
pub fn distcheck(build: &Build) {
if build.config.build != "x86_64-unknown-linux-gnu" {
use std::path::{Path, PathBuf};
use std::process::Command;
-use build_helper::output;
+use build_helper::{output, mtime};
use filetime::FileTime;
-use util::{exe, libdir, mtime, is_dylib, copy};
+use util::{exe, libdir, is_dylib, copy};
use {Build, Compiler, Mode};
/// Build the standard library.
///
/// This will build the specified tool with the specified `host` compiler in
/// `stage` into the normal cargo output directory.
-pub fn tool(build: &Build, stage: u32, host: &str, tool: &str) {
- println!("Building stage{} tool {} ({})", stage, tool, host);
+pub fn tool(build: &Build, stage: u32, target: &str, tool: &str) {
+ println!("Building stage{} tool {} ({})", stage, tool, target);
- let compiler = Compiler::new(stage, host);
+ let compiler = Compiler::new(stage, &build.config.build);
// FIXME: need to clear out previous tool and ideally deps, may require
// isolating output directories or require a pseudo shim step to
// let out_dir = build.cargo_out(stage, &host, Mode::Librustc, target);
// build.clear_if_dirty(&out_dir, &libstd_stamp(build, stage, &host, target));
- let mut cargo = build.cargo(&compiler, Mode::Tool, host, "build");
+ let mut cargo = build.cargo(&compiler, Mode::Tool, target, "build");
cargo.arg("--manifest-path")
.arg(build.src.join(format!("src/tools/{}/Cargo.toml", tool)));
pub cxx: Option<PathBuf>,
pub ndk: Option<PathBuf>,
pub musl_root: Option<PathBuf>,
+ pub qemu_rootfs: Option<PathBuf>,
}
/// Structure of the `config.toml` file that configuration is read from.
cxx: Option<String>,
android_ndk: Option<String>,
musl_root: Option<String>,
+ qemu_rootfs: Option<String>,
}
impl Config {
target.cxx = cfg.cxx.clone().map(PathBuf::from);
target.cc = cfg.cc.clone().map(PathBuf::from);
target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
+ target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from);
config.target_config.insert(triple.clone(), target);
}
.map(|s| s.to_string())
.collect();
}
+ "CFG_QEMU_ARMHF_ROOTFS" if value.len() > 0 => {
+ let target = "arm-unknown-linux-gnueabihf".to_string();
+ let target = self.target_config.entry(target)
+ .or_insert(Target::default());
+ target.qemu_rootfs = Some(parse_configure_path(value));
+ }
_ => {}
}
}
"README.md",
"RELEASES.md",
"configure",
- "Makefile.in"
+ "Makefile.in",
+ "x.py",
];
let src_dirs = [
"man",
use std::process::Command;
use {Build, Compiler, Mode};
-use util::{up_to_date, cp_r};
+use util::cp_r;
+use build_helper::up_to_date;
/// Invoke `rustbook` as compiled in `stage` for `target` for the doc book
/// `name` into the `out` path.
#![deny(warnings)]
+#[macro_use]
extern crate build_helper;
extern crate cmake;
extern crate filetime;
use std::path::{Component, PathBuf, Path};
use std::process::Command;
-use build_helper::{run_silent, output};
+use build_helper::{run_silent, output, mtime};
-use util::{exe, mtime, libdir, add_lib_path};
-
-/// A helper macro to `unwrap` a result except also print out details like:
-///
-/// * The file/line of the panic
-/// * The expression that failed
-/// * The error itself
-///
-/// This is currently used judiciously throughout the build system rather than
-/// using a `Result` with `try!`, but this may change one day...
-macro_rules! t {
- ($e:expr) => (match $e {
- Ok(e) => e,
- Err(e) => panic!("{} failed with {}", stringify!($e), e),
- })
-}
+use util::{exe, libdir, add_lib_path};
mod cc;
mod channel;
//
// These variables are primarily all read by
// src/bootstrap/bin/{rustc.rs,rustdoc.rs}
- cargo.env("RUSTC", self.out.join("bootstrap/debug/rustc"))
+ cargo.env("RUSTBUILD_NATIVE_DIR", self.native_dir(target))
+ .env("RUSTC", self.out.join("bootstrap/debug/rustc"))
.env("RUSTC_REAL", self.compiler_path(compiler))
.env("RUSTC_STAGE", stage.to_string())
.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string())
}
}
+ /// Directory for libraries built from C/C++ code and shared between stages.
+ fn native_dir(&self, target: &str) -> PathBuf {
+ self.out.join(target).join("native")
+ }
+
/// Root output directory for rust_test_helpers library compiled for
/// `target`
fn test_helpers_out(&self, target: &str) -> PathBuf {
- self.out.join(target).join("rust-test-helpers")
+ self.native_dir(target).join("rust-test-helpers")
}
/// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic
.map(|p| &**p)
}
+ /// Returns the root of the "rootfs" image that this target will be using,
+ /// if one was configured.
+ ///
+ /// If `Some` is returned then that means that tests for this target are
+ /// emulated with QEMU and binaries will need to be shipped to the emulator.
+ fn qemu_rootfs(&self, target: &str) -> Option<&Path> {
+ self.config.target_config.get(target)
+ .and_then(|t| t.qemu_rootfs.as_ref())
+ .map(|p| &**p)
+ }
+
/// Path to the python interpreter to use
fn python(&self) -> &Path {
self.config.python.as_ref().unwrap()
use gcc;
use Build;
-use util::{self, up_to_date};
+use util;
+use build_helper::up_to_date;
/// Compile LLVM for `target`.
pub fn llvm(build: &Build, target: &str) {
.dep(|s| s.name("libtest"))
.dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
.dep(|s| s.name("test-helpers"))
- .dep(|s| s.name("android-copy-libs"))
+ .dep(|s| s.name("emulator-copy-libs"))
.default(mode != "pretty") // pretty tests don't run everywhere
.run(move |s| {
check::compiletest(build, &s.compiler(), s.target, mode, dir)
.dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
.dep(|s| s.name("test-helpers"))
.dep(|s| s.name("debugger-scripts"))
- .dep(|s| s.name("android-copy-libs"))
+ .dep(|s| s.name("emulator-copy-libs"))
.run(move |s| check::compiletest(build, &s.compiler(), s.target,
"debuginfo-gdb", "debuginfo"));
let mut rule = rules.test("check-debuginfo", "src/test/debuginfo");
for (krate, path, _default) in krates("std_shim") {
rules.test(&krate.test_step, path)
.dep(|s| s.name("libtest"))
- .dep(|s| s.name("android-copy-libs"))
+ .dep(|s| s.name("emulator-copy-libs"))
.run(move |s| check::krate(build, &s.compiler(), s.target,
Mode::Libstd, TestKind::Test,
Some(&krate.name)));
}
rules.test("check-std-all", "path/to/nowhere")
.dep(|s| s.name("libtest"))
- .dep(|s| s.name("android-copy-libs"))
+ .dep(|s| s.name("emulator-copy-libs"))
.default(true)
.run(move |s| check::krate(build, &s.compiler(), s.target,
Mode::Libstd, TestKind::Test, None));
for (krate, path, _default) in krates("std_shim") {
rules.bench(&krate.bench_step, path)
.dep(|s| s.name("libtest"))
- .dep(|s| s.name("android-copy-libs"))
+ .dep(|s| s.name("emulator-copy-libs"))
.run(move |s| check::krate(build, &s.compiler(), s.target,
Mode::Libstd, TestKind::Bench,
Some(&krate.name)));
}
rules.bench("bench-std-all", "path/to/nowhere")
.dep(|s| s.name("libtest"))
- .dep(|s| s.name("android-copy-libs"))
+ .dep(|s| s.name("emulator-copy-libs"))
.default(true)
.run(move |s| check::krate(build, &s.compiler(), s.target,
Mode::Libstd, TestKind::Bench, None));
for (krate, path, _default) in krates("test_shim") {
rules.test(&krate.test_step, path)
.dep(|s| s.name("libtest"))
- .dep(|s| s.name("android-copy-libs"))
+ .dep(|s| s.name("emulator-copy-libs"))
.run(move |s| check::krate(build, &s.compiler(), s.target,
Mode::Libtest, TestKind::Test,
Some(&krate.name)));
}
rules.test("check-test-all", "path/to/nowhere")
.dep(|s| s.name("libtest"))
- .dep(|s| s.name("android-copy-libs"))
+ .dep(|s| s.name("emulator-copy-libs"))
.default(true)
.run(move |s| check::krate(build, &s.compiler(), s.target,
Mode::Libtest, TestKind::Test, None));
for (krate, path, _default) in krates("rustc-main") {
rules.test(&krate.test_step, path)
.dep(|s| s.name("librustc"))
- .dep(|s| s.name("android-copy-libs"))
+ .dep(|s| s.name("emulator-copy-libs"))
.host(true)
.run(move |s| check::krate(build, &s.compiler(), s.target,
Mode::Librustc, TestKind::Test,
}
rules.test("check-rustc-all", "path/to/nowhere")
.dep(|s| s.name("librustc"))
- .dep(|s| s.name("android-copy-libs"))
+ .dep(|s| s.name("emulator-copy-libs"))
.default(true)
.host(true)
.run(move |s| check::krate(build, &s.compiler(), s.target,
rules.build("test-helpers", "src/rt/rust_test_helpers.c")
.run(move |s| native::test_helpers(build, s.target));
- rules.test("android-copy-libs", "path/to/nowhere")
+
+ // Some test suites are run inside emulators, and most of our test binaries
+ // are linked dynamically which means we need to ship the standard library
+ // and such to the emulator ahead of time. This step represents this and is
+ // a dependency of all test suites.
+ //
+ // Most of the time this step is a noop (the `check::emulator_copy_libs`
+ // only does work if necessary). For some steps such as shipping data to
+ // QEMU we have to build our own tools so we've got conditional dependencies
+ // on those programs as well. Note that the QEMU client is built for the
+ // build target (us) and the server is built for the target.
+ rules.test("emulator-copy-libs", "path/to/nowhere")
.dep(|s| s.name("libtest"))
- .run(move |s| check::android_copy_libs(build, &s.compiler(), s.target));
+ .dep(move |s| {
+ if build.qemu_rootfs(s.target).is_some() {
+ s.name("tool-qemu-test-client").target(s.host).stage(0)
+ } else {
+ Step::noop()
+ }
+ })
+ .dep(move |s| {
+ if build.qemu_rootfs(s.target).is_some() {
+ s.name("tool-qemu-test-server")
+ } else {
+ Step::noop()
+ }
+ })
+ .run(move |s| check::emulator_copy_libs(build, &s.compiler(), s.target));
rules.test("check-bootstrap", "src/bootstrap")
.default(true)
rules.build("tool-build-manifest", "src/tools/build-manifest")
.dep(|s| s.name("libstd"))
.run(move |s| compile::tool(build, s.stage, s.target, "build-manifest"));
+ rules.build("tool-qemu-test-server", "src/tools/qemu-test-server")
+ .dep(|s| s.name("libstd"))
+ .run(move |s| compile::tool(build, s.stage, s.target, "qemu-test-server"));
+ rules.build("tool-qemu-test-client", "src/tools/qemu-test-client")
+ .dep(|s| s.name("libstd"))
+ .run(move |s| compile::tool(build, s.stage, s.target, "qemu-test-client"));
// ========================================================================
// Documentation targets
use std::process::Command;
use std::time::Instant;
-use filetime::FileTime;
-
/// Returns the `name` as the filename of a static library for `target`.
pub fn staticlib(name: &str, target: &str) -> String {
if target.contains("windows") {
}
}
-/// Returns the last-modified time for `path`, or zero if it doesn't exist.
-pub fn mtime(path: &Path) -> FileTime {
- fs::metadata(path).map(|f| {
- FileTime::from_last_modification_time(&f)
- }).unwrap_or(FileTime::zero())
-}
-
/// Copies a file from `src` to `dst`, attempting to use hard links and then
/// falling back to an actually filesystem copy if necessary.
pub fn copy(src: &Path, dst: &Path) {
cmd.env(dylib_path_var(), t!(env::join_paths(list)));
}
-/// Returns whether `dst` is up to date given that the file or files in `src`
-/// are used to generate it.
-///
-/// Uses last-modified time checks to verify this.
-pub fn up_to_date(src: &Path, dst: &Path) -> bool {
- let threshold = mtime(dst);
- let meta = match fs::metadata(src) {
- Ok(meta) => meta,
- Err(e) => panic!("source {:?} failed to get metadata: {}", src, e),
- };
- if meta.is_dir() {
- dir_up_to_date(src, &threshold)
- } else {
- FileTime::from_last_modification_time(&meta) <= threshold
- }
-}
-
-fn dir_up_to_date(src: &Path, threshold: &FileTime) -> bool {
- t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
- let meta = t!(e.metadata());
- if meta.is_dir() {
- dir_up_to_date(&e.path(), threshold)
- } else {
- FileTime::from_last_modification_time(&meta) < *threshold
- }
- })
-}
-
/// Returns the environment variable which the dynamic library lookup path
/// resides in for this platform.
pub fn dylib_path_var() -> &'static str {
[lib]
name = "build_helper"
path = "lib.rs"
+
+[dependencies]
+filetime = "0.1"
#![deny(warnings)]
+extern crate filetime;
+
+use std::fs;
use std::process::{Command, Stdio};
use std::path::{Path, PathBuf};
+use filetime::FileTime;
+
+/// A helper macro to `unwrap` a result except also print out details like:
+///
+/// * The file/line of the panic
+/// * The expression that failed
+/// * The error itself
+///
+/// This is currently used judiciously throughout the build system rather than
+/// using a `Result` with `try!`, but this may change one day...
+#[macro_export]
+macro_rules! t {
+ ($e:expr) => (match $e {
+ Ok(e) => e,
+ Err(e) => panic!("{} failed with {}", stringify!($e), e),
+ })
+}
+
pub fn run(cmd: &mut Command) {
println!("running: {:?}", cmd);
run_silent(cmd);
String::from_utf8(output.stdout).unwrap()
}
+pub fn rerun_if_changed_anything_in_dir(dir: &Path) {
+ let mut stack = dir.read_dir().unwrap()
+ .map(|e| e.unwrap())
+ .filter(|e| &*e.file_name() != ".git")
+ .collect::<Vec<_>>();
+ while let Some(entry) = stack.pop() {
+ let path = entry.path();
+ if entry.file_type().unwrap().is_dir() {
+ stack.extend(path.read_dir().unwrap().map(|e| e.unwrap()));
+ } else {
+ println!("cargo:rerun-if-changed={}", path.display());
+ }
+ }
+}
+
+/// Returns the last-modified time for `path`, or zero if it doesn't exist.
+pub fn mtime(path: &Path) -> FileTime {
+ fs::metadata(path).map(|f| {
+ FileTime::from_last_modification_time(&f)
+ }).unwrap_or(FileTime::zero())
+}
+
+/// Returns whether `dst` is up to date given that the file or files in `src`
+/// are used to generate it.
+///
+/// Uses last-modified time checks to verify this.
+pub fn up_to_date(src: &Path, dst: &Path) -> bool {
+ let threshold = mtime(dst);
+ let meta = match fs::metadata(src) {
+ Ok(meta) => meta,
+ Err(e) => panic!("source {:?} failed to get metadata: {}", src, e),
+ };
+ if meta.is_dir() {
+ dir_up_to_date(src, &threshold)
+ } else {
+ FileTime::from_last_modification_time(&meta) <= threshold
+ }
+}
+
+fn dir_up_to_date(src: &Path, threshold: &FileTime) -> bool {
+ t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
+ let meta = t!(e.metadata());
+ if meta.is_dir() {
+ dir_up_to_date(&e.path(), threshold)
+ } else {
+ FileTime::from_last_modification_time(&meta) < *threshold
+ }
+ })
+}
+
fn fail(s: &str) -> ! {
println!("\n\n{}\n\n", s);
std::process::exit(1);
--- /dev/null
+FROM ubuntu:16.04
+
+RUN apt-get update -y && apt-get install -y --no-install-recommends \
+ bc \
+ bzip2 \
+ ca-certificates \
+ cmake \
+ cpio \
+ curl \
+ file \
+ g++ \
+ gcc-arm-linux-gnueabihf \
+ git \
+ libc6-dev \
+ libc6-dev-armhf-cross \
+ make \
+ python2.7 \
+ qemu-system-arm \
+ xz-utils
+
+ENV ARCH=arm \
+ CROSS_COMPILE=arm-linux-gnueabihf-
+
+WORKDIR /build
+
+# Compile the kernel that we're going to run and be emulating with. This is
+# basically just done to be compatible with the QEMU target that we're going
+# to be using when running tests. If any other kernel works or if any
+# other QEMU target works with some other stock kernel, we can use that too!
+#
+# The `vexpress_config` config file was a previously generated config file for
+# the kernel. This file was generated by running `make vexpress_defconfig`
+# followed by `make menuconfig` and then enabling the IPv6 protocol page.
+COPY vexpress_config /build/.config
+RUN curl https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.42.tar.xz | \
+ tar xJf - && \
+ cd /build/linux-4.4.42 && \
+ cp /build/.config . && \
+ make -j$(nproc) all && \
+ cp arch/arm/boot/zImage /tmp && \
+ cd /build && \
+ rm -rf linux-4.4.42
+
+# Compile an instance of busybox as this provides a lightweight system and init
+# binary which we will boot into. Only trick here is configuring busybox to
+# build static binaries.
+RUN curl https://www.busybox.net/downloads/busybox-1.21.1.tar.bz2 | tar xjf - && \
+ cd busybox-1.21.1 && \
+ make defconfig && \
+ sed -i 's/.*CONFIG_STATIC.*/CONFIG_STATIC=y/' .config && \
+ make -j$(nproc) && \
+ make install && \
+ mv _install /tmp/rootfs && \
+ cd /build && \
+ rm -rf busybox-1.12.1
+
+# Download the ubuntu rootfs, which we'll use as a chroot for all our tests.
+WORKDIR /tmp
+RUN mkdir rootfs/ubuntu
+RUN curl http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/ubuntu-base-16.04-core-armhf.tar.gz | \
+ tar xzf - -C rootfs/ubuntu && \
+ cd rootfs && mkdir proc sys dev etc etc/init.d
+
+# Copy over our init script, which starts up our test server and also a few
+# other misc tasks.
+COPY rcS rootfs/etc/init.d/rcS
+RUN chmod +x rootfs/etc/init.d/rcS
+
+# Helper to quickly fill the entropy pool in the kernel.
+COPY addentropy.c /tmp/
+RUN arm-linux-gnueabihf-gcc addentropy.c -o rootfs/addentropy -static
+
+# TODO: What is this?!
+RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/current/images/device-tree/vexpress-v2p-ca15-tc1.dtb
+
+ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
+RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
+ tar xJf - -C /usr/local/bin --strip-components=1
+
+RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
+ dpkg -i dumb-init_*.deb && \
+ rm dumb-init_*.deb
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
+
+ENV RUST_CONFIGURE_ARGS \
+ --target=arm-unknown-linux-gnueabihf \
+ --qemu-armhf-rootfs=/tmp/rootfs
+ENV SCRIPT python2.7 ../x.py test --target arm-unknown-linux-gnueabihf
+
+ENV NO_CHANGE_USER=1
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#include <assert.h>
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <linux/random.h>
+
+#define N 2048
+
+struct entropy {
+ int ent_count;
+ int size;
+ unsigned char data[N];
+};
+
+int main() {
+ struct entropy buf;
+ ssize_t n;
+
+ int random_fd = open("/dev/random", O_RDWR);
+ assert(random_fd >= 0);
+
+ while ((n = read(0, &buf.data, N)) > 0) {
+ buf.ent_count = n * 8;
+ buf.size = n;
+ if (ioctl(random_fd, RNDADDENTROPY, &buf) != 0) {
+ perror("failed to add entropy");
+ }
+ }
+
+ return 0;
+}
--- /dev/null
+#!/bin/sh
+mount -t proc none /proc
+mount -t sysfs none /sys
+/sbin/mdev -s
+
+# fill up our entropy pool, if we don't do this then anything with a hash map
+# will likely block forever as the kernel is pretty unlikely to have enough
+# entropy.
+/addentropy < /addentropy
+cat /dev/urandom | head -n 2048 | /addentropy
+
+# Set up IP that qemu expects. This confgures eth0 with the public IP that QEMU
+# will communicate to as well as the loopback 127.0.0.1 address.
+ifconfig eth0 10.0.2.15
+ifconfig lo up
+
+# Configure DNS resolution of 'localhost' to work
+echo 'hosts: files dns' >> /ubuntu/etc/nsswitch.conf
+echo '127.0.0.1 localhost' >> /ubuntu/etc/hosts
+
+# prepare the chroot
+mount -t proc proc /ubuntu/proc/
+mount --rbind /sys /ubuntu/sys/
+mount --rbind /dev /ubuntu/dev/
+
+# Execute our `testd` inside the ubuntu chroot
+cp /testd /ubuntu/testd
+chroot /ubuntu /testd &
--- /dev/null
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.4.42 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_NO_IOPORT_MAP=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+# CONFIG_IRQ_DOMAIN_DEBUG is not set
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_ARCH_HAS_TICK_BROADCAST=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ_FULL is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+CONFIG_RCU_STALL_COMMON=y
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+CONFIG_BUILD_BIN2C=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CGROUP_PIDS is not set
+# CONFIG_CGROUP_DEVICE is not set
+CONFIG_CPUSETS=y
+CONFIG_PROC_PID_CPUSET=y
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_MEMCG is not set
+# CONFIG_CGROUP_PERF is not set
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_RD_LZO=y
+CONFIG_RD_LZ4=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+# CONFIG_EXPERT is not set
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+CONFIG_SLUB_CPU_PARTIAL=y
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+CONFIG_MODULES_TREE_LOOKUP=y
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Multiple platform selection
+#
+
+#
+# CPU Core family selection
+#
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_MULTI_V6_V7=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+# CONFIG_ARCH_VIRT is not set
+# CONFIG_ARCH_MVEBU is not set
+# CONFIG_ARCH_ALPINE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM is not set
+# CONFIG_ARCH_BERLIN is not set
+# CONFIG_ARCH_DIGICOLOR is not set
+# CONFIG_ARCH_HIGHBANK is not set
+# CONFIG_ARCH_HISI is not set
+# CONFIG_ARCH_KEYSTONE is not set
+# CONFIG_ARCH_MESON is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MEDIATEK is not set
+
+#
+# TI OMAP/AM/DM/DRA Family
+#
+# CONFIG_ARCH_OMAP3 is not set
+# CONFIG_ARCH_OMAP4 is not set
+# CONFIG_SOC_OMAP5 is not set
+# CONFIG_SOC_AM33XX is not set
+# CONFIG_SOC_AM43XX is not set
+# CONFIG_SOC_DRA7XX is not set
+# CONFIG_ARCH_QCOM is not set
+# CONFIG_ARCH_ROCKCHIP is not set
+# CONFIG_ARCH_SOCFPGA is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_STI is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_SHMOBILE_MULTI is not set
+# CONFIG_ARCH_SUNXI is not set
+# CONFIG_ARCH_SIRF is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_UNIPHIER is not set
+# CONFIG_ARCH_U8500 is not set
+CONFIG_ARCH_VEXPRESS=y
+CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y
+CONFIG_ARCH_VEXPRESS_DCSCB=y
+CONFIG_ARCH_VEXPRESS_SPC=y
+CONFIG_ARCH_VEXPRESS_TC2_PM=y
+# CONFIG_ARCH_WM8850 is not set
+# CONFIG_ARCH_ZX is not set
+# CONFIG_ARCH_ZYNQ is not set
+CONFIG_PLAT_VERSATILE=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_VIRT_EXT=y
+CONFIG_SWP_EMULATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+CONFIG_VDSO=y
+CONFIG_OUTER_CACHE=y
+CONFIG_OUTER_CACHE_SYNC=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+CONFIG_CACHE_L2X0=y
+# CONFIG_PL310_ERRATA_588369 is not set
+# CONFIG_PL310_ERRATA_727915 is not set
+CONFIG_PL310_ERRATA_753970=y
+# CONFIG_PL310_ERRATA_769419 is not set
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+CONFIG_ARM_HEAVY_MB=y
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+# CONFIG_ARM_KERNMEM_PERMS is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_430973 is not set
+CONFIG_ARM_ERRATA_643719=y
+CONFIG_ARM_ERRATA_720789=y
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_754327 is not set
+# CONFIG_ARM_ERRATA_764369 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
+# CONFIG_ARM_ERRATA_798181 is not set
+# CONFIG_ARM_ERRATA_773022 is not set
+CONFIG_ICST=y
+
+#
+# Bus support
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_HAVE_SMP=y
+CONFIG_SMP=y
+CONFIG_SMP_ON_UP=y
+CONFIG_ARM_CPU_TOPOLOGY=y
+# CONFIG_SCHED_MC is not set
+# CONFIG_SCHED_SMT is not set
+CONFIG_HAVE_ARM_SCU=y
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_HAVE_ARM_TWD=y
+CONFIG_MCPM=y
+# CONFIG_BIG_LITTLE is not set
+# CONFIG_VMSPLIT_3G is not set
+# CONFIG_VMSPLIT_3G_OPT is not set
+CONFIG_VMSPLIT_2G=y
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_NR_CPUS=8
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARM_PSCI=y
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_CPU_SW_DOMAIN_PAN=y
+CONFIG_HW_PERF_EVENTS=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+CONFIG_MEMORY_ISOLATION=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MEMORY_BALLOON=y
+CONFIG_BALLOON_COMPACTION=y
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_CLEANCACHE is not set
+# CONFIG_FRONTSWAP is not set
+CONFIG_CMA=y
+# CONFIG_CMA_DEBUG is not set
+# CONFIG_CMA_DEBUGFS is not set
+CONFIG_CMA_AREAS=7
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_XEN is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_ARM_APPENDED_DTB is not set
+CONFIG_CMDLINE="console=ttyAMA0"
+CONFIG_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_CMDLINE_EXTEND is not set
+# CONFIG_CMDLINE_FORCE is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# ARM CPU Idle Drivers
+#
+# CONFIG_ARM_CPUIDLE is not set
+# CONFIG_ARM_BIG_LITTLE_CPUIDLE is not set
+# CONFIG_ARM_HIGHBANK_CPUIDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_KERNEL_MODE_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_HIBERNATION is not set
+CONFIG_PM_SLEEP=y
+CONFIG_PM_SLEEP_SMP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_PM_OPP=y
+CONFIG_PM_CLK=y
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=m
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_IPV6_ILA is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_GRE is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_MMAP is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+CONFIG_RPS=y
+CONFIG_RFS_ACCEL=y
+CONFIG_XPS=y
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+CONFIG_NET_FLOW_LIMIT=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_RFKILL_REGULATOR is not set
+CONFIG_NET_9P=y
+CONFIG_NET_9P_VIRTIO=y
+# CONFIG_NET_9P_DEBUG is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+CONFIG_HAVE_BPF_JIT=y
+
+#
+# Device Drivers
+#
+CONFIG_ARM_AMBA=y
+# CONFIG_TEGRA_AHB is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+# CONFIG_DEVTMPFS_MOUNT is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+# CONFIG_DMA_SHARED_BUFFER is not set
+# CONFIG_DMA_CMA is not set
+
+#
+# Bus devices
+#
+CONFIG_ARM_CCI=y
+CONFIG_ARM_CCI400_COMMON=y
+# CONFIG_ARM_CCI400_PMU is not set
+CONFIG_ARM_CCI400_PORT_CTRL=y
+# CONFIG_ARM_CCI500_PMU is not set
+# CONFIG_ARM_CCN is not set
+# CONFIG_BRCMSTB_GISB_ARB is not set
+CONFIG_VEXPRESS_CONFIG=y
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_SWAP is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_PLATRAM=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+# CONFIG_MTD_SPI_NOR is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_BLOCK is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_MTD=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+CONFIG_VIRTIO_BLK=y
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_ARM_CHARLCD is not set
+# CONFIG_BMP085_I2C is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_SRAM is not set
+CONFIG_VEXPRESS_SYSCFG=y
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_KERNEL_API is not set
+# CONFIG_CXL_EEH is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_MQ_DEFAULT is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_SCSI_UFSHCD is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_SCSI_VIRTIO=y
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+CONFIG_HAVE_PATA_PLATFORM=y
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
+# CONFIG_SATA_PMP is not set
+
+#
+# Controllers with non-SFF native interface
+#
+# CONFIG_SATA_AHCI_PLATFORM is not set
+# CONFIG_AHCI_CEVA is not set
+# CONFIG_AHCI_QORIQ is not set
+CONFIG_ATA_SFF=y
+
+#
+# SFF controllers with custom DMA interface
+#
+CONFIG_ATA_BMDMA=y
+
+#
+# SATA SFF controllers with BMDMA
+#
+
+#
+# PATA SFF controllers with BMDMA
+#
+
+#
+# PIO-only SFF controllers
+#
+# CONFIG_PATA_PLATFORM is not set
+
+#
+# Generic fallback / legacy drivers
+#
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_IPVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+CONFIG_VIRTIO_NET=y
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+CONFIG_NET_VENDOR_ARC=y
+# CONFIG_ARC_EMAC is not set
+# CONFIG_EMAC_ROCKCHIP is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+CONFIG_NET_CADENCE=y
+# CONFIG_MACB is not set
+CONFIG_NET_VENDOR_BROADCOM=y
+# CONFIG_B44 is not set
+# CONFIG_BCMGENET is not set
+# CONFIG_SYSTEMPORT is not set
+CONFIG_NET_VENDOR_CIRRUS=y
+# CONFIG_CS89x0 is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+CONFIG_NET_VENDOR_EZCHIP=y
+# CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set
+CONFIG_NET_VENDOR_FARADAY=y
+# CONFIG_FTMAC100 is not set
+# CONFIG_FTGMAC100 is not set
+CONFIG_NET_VENDOR_HISILICON=y
+# CONFIG_HIX5HD2_GMAC is not set
+# CONFIG_HIP04_ETH is not set
+# CONFIG_HNS is not set
+# CONFIG_HNS_DSAF is not set
+# CONFIG_HNS_ENET is not set
+CONFIG_NET_VENDOR_INTEL=y
+CONFIG_NET_VENDOR_I825XX=y
+CONFIG_NET_VENDOR_MARVELL=y
+# CONFIG_MVMDIO is not set
+CONFIG_NET_VENDOR_MICREL=y
+# CONFIG_KS8851_MLL is not set
+CONFIG_NET_VENDOR_NATSEMI=y
+CONFIG_NET_VENDOR_8390=y
+# CONFIG_AX88796 is not set
+# CONFIG_ETHOC is not set
+CONFIG_NET_VENDOR_QUALCOMM=y
+CONFIG_NET_VENDOR_RENESAS=y
+CONFIG_NET_VENDOR_ROCKER=y
+CONFIG_NET_VENDOR_SAMSUNG=y
+# CONFIG_SXGBE_ETH is not set
+CONFIG_NET_VENDOR_SEEQ=y
+CONFIG_NET_VENDOR_SMSC=y
+CONFIG_SMC91X=y
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=y
+# CONFIG_SMSC911X_ARCH_HOOKS is not set
+CONFIG_NET_VENDOR_STMICRO=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NET_VENDOR_SYNOPSYS=y
+# CONFIG_SYNOPSYS_DWC_ETH_QOS is not set
+CONFIG_NET_VENDOR_VIA=y
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_NET_VENDOR_WIZNET=y
+# CONFIG_WIZNET_W5100 is not set
+# CONFIG_WIZNET_W5300 is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_AMD_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_LAN78XX is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_LEDS=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_TCA8418 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_LM8333 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_OMAP4 is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_CAP11XX is not set
+# CONFIG_KEYBOARD_BCM is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_PS2_FOCALTECH=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_CYAPA is not set
+# CONFIG_MOUSE_ELAN_I2C is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_MOUSE_SYNAPTICS_USB is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_AMBAKMI=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_SERIO_APBPS2 is not set
+# CONFIG_USERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+CONFIG_DEVKMEM=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+CONFIG_HVC_DRIVER=y
+# CONFIG_HVC_DCC is not set
+CONFIG_VIRTIO_CONSOLE=y
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+CONFIG_HW_RANDOM_VIRTIO=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+# CONFIG_I2C_CHARDEV is not set
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_NOMADIK is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+CONFIG_I2C_VERSATILE=y
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_SPI is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_DEVRES=y
+CONFIG_OF_GPIO=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+CONFIG_GPIO_GENERIC=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+CONFIG_GPIO_GENERIC_PLATFORM=y
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_PL061 is not set
+# CONFIG_GPIO_SYSCON is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+
+#
+# MFD GPIO expanders
+#
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27XXX is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_LP8727 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_CHARGER_MANAGER is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_BQ24190 is not set
+# CONFIG_CHARGER_BQ24735 is not set
+# CONFIG_CHARGER_BQ25890 is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_CHARGER_RT9455 is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMSTB is not set
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_VERSATILE is not set
+CONFIG_POWER_RESET_VEXPRESS=y
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7410 is not set
+# CONFIG_SENSORS_ADT7411 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ASC7621 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS620 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_G762 is not set
+# CONFIG_SENSORS_GPIO_FAN is not set
+# CONFIG_SENSORS_HIH6130 is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_JC42 is not set
+# CONFIG_SENSORS_POWR1220 is not set
+# CONFIG_SENSORS_LINEAGE is not set
+# CONFIG_SENSORS_LTC2945 is not set
+# CONFIG_SENSORS_LTC4151 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4222 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LTC4260 is not set
+# CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_MAX16065 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX1668 is not set
+# CONFIG_SENSORS_MAX197 is not set
+# CONFIG_SENSORS_MAX6639 is not set
+# CONFIG_SENSORS_MAX6642 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_MAX6697 is not set
+# CONFIG_SENSORS_MAX31790 is not set
+# CONFIG_SENSORS_HTU21 is not set
+# CONFIG_SENSORS_MCP3021 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM73 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LM95234 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_LM95245 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_NTC_THERMISTOR is not set
+# CONFIG_SENSORS_NCT6683 is not set
+# CONFIG_SENSORS_NCT6775 is not set
+# CONFIG_SENSORS_NCT7802 is not set
+# CONFIG_SENSORS_NCT7904 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_PMBUS is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SHT21 is not set
+# CONFIG_SENSORS_SHTC1 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_EMC1403 is not set
+# CONFIG_SENSORS_EMC2103 is not set
+# CONFIG_SENSORS_EMC6W201 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SCH56XX_COMMON is not set
+# CONFIG_SENSORS_SMM665 is not set
+# CONFIG_SENSORS_ADC128D818 is not set
+# CONFIG_SENSORS_ADS1015 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_AMC6821 is not set
+# CONFIG_SENSORS_INA209 is not set
+# CONFIG_SENSORS_INA2XX is not set
+# CONFIG_SENSORS_TC74 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP102 is not set
+# CONFIG_SENSORS_TMP103 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+CONFIG_SENSORS_VEXPRESS=y
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83795 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_UCB1400_CORE is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+CONFIG_MFD_SYSCON=y
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+CONFIG_MFD_VEXPRESS_SYSREG=y
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_ACT8865 is not set
+# CONFIG_REGULATOR_AD5398 is not set
+# CONFIG_REGULATOR_ANATOP is not set
+# CONFIG_REGULATOR_DA9210 is not set
+# CONFIG_REGULATOR_DA9211 is not set
+# CONFIG_REGULATOR_FAN53555 is not set
+# CONFIG_REGULATOR_GPIO is not set
+# CONFIG_REGULATOR_ISL9305 is not set
+# CONFIG_REGULATOR_ISL6271A is not set
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_REGULATOR_LP3972 is not set
+# CONFIG_REGULATOR_LP872X is not set
+# CONFIG_REGULATOR_LP8755 is not set
+# CONFIG_REGULATOR_LTC3589 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_MAX8649 is not set
+# CONFIG_REGULATOR_MAX8660 is not set
+# CONFIG_REGULATOR_MAX8952 is not set
+# CONFIG_REGULATOR_MAX8973 is not set
+# CONFIG_REGULATOR_MT6311 is not set
+# CONFIG_REGULATOR_PFUZE100 is not set
+# CONFIG_REGULATOR_TPS51632 is not set
+# CONFIG_REGULATOR_TPS62360 is not set
+# CONFIG_REGULATOR_TPS65023 is not set
+# CONFIG_REGULATOR_TPS6507X is not set
+CONFIG_REGULATOR_VEXPRESS=y
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_CMDLINE=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_ARMCLCD=y
+CONFIG_PLAT_VERSATILE_CLCD=y
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_FB_SSD1307 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEOMODE_HELPERS=y
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_PCM_TIMER=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_PROC_FS=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_VMASTER=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_AC97_CODEC=y
+# CONFIG_SND_DRIVERS is not set
+
+#
+# HD-Audio
+#
+CONFIG_SND_HDA_PREALLOC_SIZE=64
+CONFIG_SND_ARM=y
+CONFIG_SND_ARMAACI=y
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_UA101 is not set
+# CONFIG_SND_USB_CAIAQ is not set
+# CONFIG_SND_USB_6FIRE is not set
+# CONFIG_SND_USB_HIFACE is not set
+# CONFIG_SND_BCD2000 is not set
+# CONFIG_SND_USB_POD is not set
+# CONFIG_SND_USB_PODHD is not set
+# CONFIG_SND_USB_TONEPORT is not set
+# CONFIG_SND_USB_VARIAX is not set
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=y
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+# CONFIG_HID_ACRUX is not set
+CONFIG_HID_APPLE=y
+# CONFIG_HID_APPLEIR is not set
+# CONFIG_HID_AUREAL is not set
+CONFIG_HID_BELKIN=y
+# CONFIG_HID_BETOP_FF is not set
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+# CONFIG_HID_CORSAIR is not set
+# CONFIG_HID_PRODIKEYS is not set
+# CONFIG_HID_CP2112 is not set
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_ELO is not set
+CONFIG_HID_EZKEY=y
+# CONFIG_HID_GEMBIRD is not set
+# CONFIG_HID_GFRM is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_GT683R is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+CONFIG_HID_GYRATION=y
+# CONFIG_HID_ICADE is not set
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO is not set
+CONFIG_HID_LOGITECH=y
+# CONFIG_HID_LOGITECH_HIDPP is not set
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+# CONFIG_LOGIG940_FF is not set
+# CONFIG_LOGIWHEELS_FF is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_MULTITOUCH is not set
+CONFIG_HID_NTRIG=y
+# CONFIG_HID_ORTEK is not set
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+# CONFIG_HID_PENMOUNT is not set
+CONFIG_HID_PETALYNX=y
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PLANTRONICS is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+# CONFIG_SONY_FF is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+CONFIG_HID_SUNPLUS=y
+# CONFIG_HID_RMI is not set
+CONFIG_HID_GREENASIA=y
+# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_SMARTJOYPLUS=y
+# CONFIG_SMARTJOYPLUS_FF is not set
+# CONFIG_HID_TIVO is not set
+CONFIG_HID_TOPSEED=y
+# CONFIG_HID_THINGM is not set
+CONFIG_HID_THRUSTMASTER=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_WIIMOTE is not set
+# CONFIG_HID_XINMO is not set
+CONFIG_HID_ZEROPLUS=y
+# CONFIG_ZEROPLUS_FF is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_ULPI_BUS is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+# CONFIG_USB_DWC2 is not set
+CONFIG_USB_ISP1760=y
+CONFIG_USB_ISP1760_HCD=y
+CONFIG_USB_ISP1760_HOST_ROLE=y
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+# CONFIG_USB_CHAOSKEY is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_AM335X_PHY_USB is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_LED_TRIG is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_ARMMMCI=y
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+# CONFIG_LEDS_CLASS_FLASH is not set
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_BCM6328 is not set
+# CONFIG_LEDS_BCM6358 is not set
+# CONFIG_LEDS_LM3530 is not set
+# CONFIG_LEDS_LM3642 is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+# CONFIG_LEDS_LP5562 is not set
+# CONFIG_LEDS_LP8501 is not set
+# CONFIG_LEDS_LP8860 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_PCA963X is not set
+# CONFIG_LEDS_REGULATOR is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+# CONFIG_LEDS_TCA6507 is not set
+# CONFIG_LEDS_TLC591XX is not set
+# CONFIG_LEDS_LM355x is not set
+
+#
+# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)
+#
+# CONFIG_LEDS_BLINKM is not set
+# CONFIG_LEDS_SYSCON is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+# CONFIG_LEDS_TRIGGER_ONESHOT is not set
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+CONFIG_LEDS_TRIGGER_CPU=y
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_LEDS_TRIGGER_TRANSIENT is not set
+# CONFIG_LEDS_TRIGGER_CAMERA is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_ISL12057 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF2127 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_ZYNQMP is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PL030 is not set
+CONFIG_RTC_DRV_PL031=y
+# CONFIG_RTC_DRV_SNVS is not set
+
+#
+# HID Sensor RTC drivers
+#
+# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+CONFIG_VIRTIO=y
+
+#
+# Virtio drivers
+#
+CONFIG_VIRTIO_BALLOON=y
+# CONFIG_VIRTIO_INPUT is not set
+CONFIG_VIRTIO_MMIO=y
+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+CONFIG_COMMON_CLK_VERSATILE=y
+CONFIG_CLK_SP810=y
+CONFIG_CLK_VEXPRESS_OSC=y
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+CONFIG_ARM_GLOBAL_TIMER=y
+CONFIG_ARM_TIMER_SP804=y
+CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+CONFIG_CLKSRC_VERSATILE=y
+# CONFIG_MAILBOX is not set
+CONFIG_IOMMU_SUPPORT=y
+
+#
+# Generic IOMMU Pagetable Support
+#
+# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set
+# CONFIG_ARM_SMMU is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+CONFIG_ARM_PMU=y
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_STM_DUMMY is not set
+# CONFIG_STM_SOURCE_CONSOLE is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# Firmware Drivers
+#
+CONFIG_ARM_PSCI_FW=y
+# CONFIG_FIRMWARE_MEMMAP is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_ENCRYPTION is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_ATIME_SUPPORT is not set
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_FILE_CACHE=y
+# CONFIG_SQUASHFS_FILE_DIRECT is not set
+CONFIG_SQUASHFS_DECOMP_SINGLE=y
+# CONFIG_SQUASHFS_DECOMP_MULTI is not set
+# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set
+# CONFIG_SQUASHFS_XATTR is not set
+CONFIG_SQUASHFS_ZLIB=y
+# CONFIG_SQUASHFS_LZ4 is not set
+CONFIG_SQUASHFS_LZO=y
+# CONFIG_SQUASHFS_XZ is not set
+# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=y
+# CONFIG_9P_FS_POSIX_ACL is not set
+# CONFIG_9P_FS_SECURITY is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO_REDUCED is not set
+# CONFIG_DEBUG_INFO_SPLIT is not set
+# CONFIG_DEBUG_INFO_DWARF4 is not set
+# CONFIG_GDB_SCRIPTS is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHED_INFO is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+# CONFIG_STACKTRACE is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=21
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACE_CLOCK=y
+CONFIG_RING_BUFFER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_UPROBE_EVENT is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_RING_BUFFER_STARTUP_TEST is not set
+CONFIG_TRACING_EVENTS_GPIO=y
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARM_PTDUMP is not set
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=m
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_AKCIPHER2=y
+# CONFIG_CRYPTO_RSA is not set
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_NULL2=y
+# CONFIG_CRYPTO_PCRYPT is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+# CONFIG_CRYPTO_SEQIV is not set
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=m
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=m
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG_CTR is not set
+CONFIG_CRYPTO_DRBG=m
+CONFIG_CRYPTO_JITTERENTROPY=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+# CONFIG_CRYPTO_HW is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_DECOMPRESS_LZ4=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
+CONFIG_CPU_RMAP=y
+CONFIG_DQL=y
+CONFIG_GLOB=y
+# CONFIG_GLOB_SELFTEST is not set
+CONFIG_NLATTR=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+CONFIG_LIBFDT=y
+CONFIG_FONT_SUPPORT=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_SG_SPLIT is not set
+CONFIG_ARCH_HAS_SG_CHAIN=y
+# CONFIG_VIRTUALIZATION is not set
set -e
-if [ "$LOCAL_USER_ID" != "" ]; then
- useradd --shell /bin/bash -u $LOCAL_USER_ID -o -c "" -m user
- export HOME=/home/user
- unset LOCAL_USER_ID
- exec su --preserve-environment -c "env PATH=$PATH \"$0\"" user
+if [ "$NO_CHANGE_USER" = "" ]; then
+ if [ "$LOCAL_USER_ID" != "" ]; then
+ useradd --shell /bin/bash -u $LOCAL_USER_ID -o -c "" -m user
+ export HOME=/home/user
+ unset LOCAL_USER_ID
+ exec su --preserve-environment -c "env PATH=$PATH \"$0\"" user
+ fi
fi
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-sccache"
## `Cell<T>`
-[`Cell<T>`][cell] is a type that provides zero-cost interior mutability, but only for `Copy` types.
+[`Cell<T>`][cell] is a type that provides zero-cost interior mutability by moving data in and
+out of the cell.
Since the compiler knows that all the data owned by the contained value is on the stack, there's
no worry of leaking any data behind references (or worse!) by simply replacing the data.
unnecessary. However, this also relaxes the guarantees that the restriction provides; so if your
invariants depend on data stored within `Cell`, you should be careful.
-This is useful for mutating primitives and other `Copy` types when there is no easy way of
+This is useful for mutating primitives and other types when there is no easy way of
doing it in line with the static rules of `&` and `&mut`.
`Cell` does not let you obtain interior references to the data, which makes it safe to freely
#### Cost
-There is no runtime cost to using `Cell<T>`, however if you are using it to wrap larger (`Copy`)
+There is no runtime cost to using `Cell<T>`, however if you are using it to wrap larger
structs, it might be worthwhile to instead wrap individual fields in `Cell<T>` since each write is
otherwise a full copy of the struct.
## `RefCell<T>`
-[`RefCell<T>`][refcell] also provides interior mutability, but isn't restricted to `Copy` types.
+[`RefCell<T>`][refcell] also provides interior mutability, but doesn't move data in and out of the
+cell.
-Instead, it has a runtime cost. `RefCell<T>` enforces the read-write lock pattern at runtime (it's
+However, it has a runtime cost. `RefCell<T>` enforces the read-write lock pattern at runtime (it's
like a single-threaded mutex), unlike `&T`/`&mut T` which do so at compile time. This is done by the
`borrow()` and `borrow_mut()` functions, which modify an internal reference count and return smart
pointers which can be dereferenced immutably and mutably respectively. The refcount is restored when
to generate warnings or errors, when an item is missing documentation.
To generate warnings you use `warn`:
-```rust
+```rust,ignore
#![warn(missing_docs)]
```
You can control a few aspects of the HTML that `rustdoc` generates through the
`#![doc]` version of the attribute:
-```rust
+```rust,ignore
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/")]
% if let
-`if let` allows you to combine `if` and `let` together to reduce the overhead
-of certain kinds of pattern matches.
+`if let` permits [patterns][pattern] matching within the condition of an [if][if] statement.
+This allows us to reduce the overhead of certain kinds of [pattern][patterns] matches
+and express them in a more convenient way.
For example, let’s say we have some sort of `Option<T>`. We want to call a function
on it if it’s `Some<T>`, but do nothing if it’s `None`. That looks like this:
```
[patterns]: patterns.html
+[if]: if.html
That's all there is to the `tests` directory. The `tests` module isn't needed
here, since the whole thing is focused on tests.
+Note, when building integration tests, cargo will not pass the `test` attribute
+to the compiler. It means that all parts in `cfg(test)` won't be included in
+the build used in your integration tests.
+
Let's finally check out that third section: documentation tests.
# Documentation tests
To use `#![no_std]`, add it to your crate root:
-```rust
+```rust,ignore
#![no_std]
fn plus_one(x: i32) -> i32 {
prelude](../core/prelude/v1/index.html). This means that a lot of code will Just
Work:
-```rust
+```rust,ignore
#![no_std]
fn may_fail(failure: bool) -> Result<(), &'static str> {
not access any expired data, even if its type gives it the capability
to do so.
-That attribute is called `unsafe_destructor_blind_to_params`.
+That attribute is called `may_dangle` and was introduced in [RFC 1327]
+(https://github.com/rust-lang/rfcs/blob/master/text/1327-dropck-param-eyepatch.md).
To deploy it on the Inspector example from above, we would write:
```rust,ignore
struct Inspector<'a>(&'a u8, &'static str);
-impl<'a> Drop for Inspector<'a> {
- #[unsafe_destructor_blind_to_params]
+unsafe impl<#[may_dangle] 'a> Drop for Inspector<'a> {
fn drop(&mut self) {
println!("Inspector(_, {}) knows when *not* to inspect.", self.1);
}
}
```
-This attribute has the word `unsafe` in it because the compiler is not
-checking the implicit assertion that no potentially expired data
+Use of this attribute requires the `Drop` impl to be marked `unsafe` because the
+compiler is not checking the implicit assertion that no potentially expired data
(e.g. `self.0` above) is accessed.
+The attribute can be applied to any number of lifetime and type parameters. In
+the following example, we assert that we access no data behind a reference of
+lifetime `'b` and that the only uses of `T` will be moves or drops, but omit
+the attribute from `'a` and `U`, because we do access data with that lifetime
+and that type:
+
+```rust,ignore
+use std::fmt::Display;
+
+struct Inspector<'a, 'b, T, U: Display>(&'a u8, &'b u8, T, U);
+
+unsafe impl<'a, #[may_dangle] 'b, #[may_dangle] T, U: Display> Drop for Inspector<'a, 'b, T, U> {
+ fn drop(&mut self) {
+ println!("Inspector({}, _, _, {})", self.0, self.3);
+ }
+}
+```
+
It is sometimes obvious that no such access can occur, like the case above.
However, when dealing with a generic type parameter, such access can
occur indirectly. Examples of such indirect access are:
directly within it.
In all of the above cases where the `&'a u8` is accessed in the
-destructor, adding the `#[unsafe_destructor_blind_to_params]`
+destructor, adding the `#[may_dangle]`
attribute makes the type vulnerable to misuse that the borrower
checker will not catch, inviting havoc. It is better to avoid adding
the attribute.
depending on build target, such as targeted operating system, or to enable
release builds.
-There are two kinds of configuration options, one that is either defined or not
-(`#[cfg(foo)]`), and the other that contains a string that can be checked
-against (`#[cfg(bar = "baz")]`). Currently, only compiler-defined configuration
-options can have the latter form.
+Configuration options are boolean (on or off) and are named either with a
+single identifier (e.g. `foo`) or an identifier and a string (e.g. `foo = "bar"`;
+the quotes are required and spaces around the `=` are unimportant). Note that
+similarly-named options, such as `foo`, `foo="bar"` and `foo="baz"` may each be set
+or unset independently.
+
+Configuration options are either provided by the compiler or passed in on the
+command line using `--cfg` (e.g. `rustc main.rs --cfg foo --cfg 'bar="baz"'`).
+Rust code then checks for their presence using the `#[cfg(...)]` attribute:
```
// The function is only included in the build when compiling for OSX
#[cfg_attr(a, b)]
```
-Will be the same as `#[b]` if `a` is set by `cfg`, and nothing otherwise.
+This is the same as `#[b]` if `a` is set by `cfg`, and nothing otherwise.
+
+Lastly, configuration options can be used in expressions by invoking the `cfg!`
+macro: `cfg!(a)` evaluates to `true` if `a` is set, and `false` otherwise.
### Lint check attributes
}
}
-#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<#[may_dangle] T: ?Sized> Drop for Box<T> {
fn drop(&mut self) {
}
}
-#[cfg(not(test))]
-#[cfg(stage0)]
-#[lang = "exchange_free"]
-#[inline]
-unsafe fn exchange_free(ptr: *mut u8, old_size: usize, align: usize) {
- deallocate(ptr, old_size, align);
-}
-
#[cfg(not(test))]
#[lang = "box_free"]
#[inline]
//! pointer to the same value in the heap. When the last [`Rc`] pointer to a
//! given value is destroyed, the pointed-to value is also destroyed.
//!
-//! Shared references in Rust disallow mutation by default, and `Rc` is no
-//! exception. If you need to mutate through an [`Rc`], use [`Cell`] or
-//! [`RefCell`].
+//! Shared references in Rust disallow mutation by default, and [`Rc`]
+//! is no exception: you cannot obtain a mutable reference to
+//! something inside an [`Rc`]. If you need mutability, put a [`Cell`]
+//! or [`RefCell`] inside the [`Rc`]; see [an example of mutability
+//! inside an Rc][mutability].
//!
//! [`Rc`] uses non-atomic reference counting. This means that overhead is very
//! low, but an [`Rc`] cannot be sent between threads, and consequently [`Rc`]
//! [upgrade]: struct.Weak.html#method.upgrade
//! [`None`]: ../../std/option/enum.Option.html#variant.None
//! [assoc]: ../../book/method-syntax.html#associated-functions
+//! [mutability]: ../../std/cell/index.html#introducing-mutability-inside-of-something-immutable
#![stable(feature = "rust1", since = "1.0.0")]
#![deny(warnings)]
+#[macro_use]
extern crate build_helper;
extern crate gcc;
use std::env;
-use std::path::PathBuf;
+use std::fs::{self, File};
+use std::path::{Path, PathBuf};
use std::process::Command;
-use build_helper::run;
+use build_helper::{run, rerun_if_changed_anything_in_dir, up_to_date};
fn main() {
println!("cargo:rustc-cfg=cargobuild");
println!("cargo:rerun-if-changed=build.rs");
- let target = env::var("TARGET").expect("TARGET was not set");
- let host = env::var("HOST").expect("HOST was not set");
- let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
- let src_dir = env::current_dir().unwrap();
-
// FIXME: This is a hack to support building targets that don't
// support jemalloc alongside hosts that do. The jemalloc build is
// controlled by a feature of the std crate, and if that feature
// that the feature set used by std is the same across all
// targets, which means we have to build the alloc_jemalloc crate
// for targets like emscripten, even if we don't use it.
+ let target = env::var("TARGET").expect("TARGET was not set");
+ let host = env::var("HOST").expect("HOST was not set");
if target.contains("rumprun") || target.contains("bitrig") || target.contains("openbsd") ||
target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") ||
target.contains("redox") {
return;
}
+ if target.contains("android") {
+ println!("cargo:rustc-link-lib=gcc");
+ } else if !target.contains("windows") && !target.contains("musl") {
+ println!("cargo:rustc-link-lib=pthread");
+ }
+
if let Some(jemalloc) = env::var_os("JEMALLOC_OVERRIDE") {
let jemalloc = PathBuf::from(jemalloc);
println!("cargo:rustc-link-search=native={}",
return;
}
+ let build_dir = env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or(env::var_os("OUT_DIR").unwrap());
+ let build_dir = PathBuf::from(build_dir).join("jemalloc");
+ let _ = fs::create_dir_all(&build_dir);
+
+ if target.contains("windows") {
+ println!("cargo:rustc-link-lib=static=jemalloc");
+ } else {
+ println!("cargo:rustc-link-lib=static=jemalloc_pic");
+ }
+ println!("cargo:rustc-link-search=native={}/lib", build_dir.display());
+ let src_dir = env::current_dir().unwrap().join("../jemalloc");
+ rerun_if_changed_anything_in_dir(&src_dir);
+ let timestamp = build_dir.join("rustbuild.timestamp");
+ if up_to_date(&Path::new("build.rs"), ×tamp) && up_to_date(&src_dir, ×tamp) {
+ return
+ }
+
let compiler = gcc::Config::new().get_compiler();
// only msvc returns None for ar so unwrap is okay
let ar = build_helper::cc2ar(compiler.path(), &target).unwrap();
.collect::<Vec<_>>()
.join(" ");
- let mut stack = src_dir.join("../jemalloc")
- .read_dir()
- .unwrap()
- .map(|e| e.unwrap())
- .filter(|e| &*e.file_name() != ".git")
- .collect::<Vec<_>>();
- while let Some(entry) = stack.pop() {
- let path = entry.path();
- if entry.file_type().unwrap().is_dir() {
- stack.extend(path.read_dir().unwrap().map(|e| e.unwrap()));
- } else {
- println!("cargo:rerun-if-changed={}", path.display());
- }
- }
-
let mut cmd = Command::new("sh");
- cmd.arg(src_dir.join("../jemalloc/configure")
+ cmd.arg(src_dir.join("configure")
.to_str()
.unwrap()
.replace("C:\\", "/c/")
}
run(&mut cmd);
+
let mut make = Command::new(build_helper::make(&host));
make.current_dir(&build_dir)
.arg("build_lib_static");
run(&mut make);
- if target.contains("windows") {
- println!("cargo:rustc-link-lib=static=jemalloc");
- } else {
- println!("cargo:rustc-link-lib=static=jemalloc_pic");
- }
- println!("cargo:rustc-link-search=native={}/lib", build_dir.display());
- if target.contains("android") {
- println!("cargo:rustc-link-lib=gcc");
- } else if !target.contains("windows") && !target.contains("musl") {
- println!("cargo:rustc-link-lib=pthread");
- }
-
// The pthread_atfork symbols is used by jemalloc on android but the really
// old android we're building on doesn't have them defined, so just make
// sure the symbols are available.
.file("pthread_atfork_dummy.c")
.compile("libpthread_atfork_dummy.a");
}
+
+ t!(File::create(×tamp));
}
// against the upstream libbacktrace, that's what's going on.
uint32_t str_size;
off_t str_off;
- struct backtrace_view syms_view;
+ // NOTE: upstream doesn't have `{0}`, this is a fix for Rust issue #39468.
+ // If syms_view is not initialized, then `free(syms_view.base)` may segfault later.
+ struct backtrace_view syms_view = {0};
off_t syms_off;
size_t syms_size;
int syms_view_valid;
sift: bool,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, T: Ord + fmt::Debug> fmt::Debug for PeekMut<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("PeekMut")
+ .field(&self.heap.data[0])
+ .finish()
+ }
+}
+
#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
impl<'a, T: Ord> Drop for PeekMut<'a, T> {
fn drop(&mut self) {
iter: slice::Iter<'a, T>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for Iter<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("Iter")
+ .field(&self.iter.as_slice())
+ .finish()
+ }
+}
+
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Clone for Iter<'a, T> {
iter: vec::IntoIter<T>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("IntoIter")
+ .field(&self.iter.as_slice())
+ .finish()
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Iterator for IntoIter<T> {
type Item = T;
/// An iterator that drains a `BinaryHeap`.
#[stable(feature = "drain", since = "1.6.0")]
+#[derive(Debug)]
pub struct Drain<'a, T: 'a> {
iter: vec::Drain<'a, T>,
}
#[unstable(feature = "fused", issue = "35602")]
impl<'a, T: 'a> FusedIterator for Drain<'a, T> {}
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
impl<T: Ord> From<Vec<T>> for BinaryHeap<T> {
fn from(vec: Vec<T>) -> BinaryHeap<T> {
let mut heap = BinaryHeap { data: vec };
}
}
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
impl<T> From<BinaryHeap<T>> for Vec<T> {
fn from(heap: BinaryHeap<T>) -> Vec<T> {
heap.data
place: vec::PlaceBack<'a, T>,
}
+#[unstable(feature = "collection_placement",
+ reason = "placement protocol is subject to change",
+ issue = "30172")]
+impl<'a, T: Clone + Ord + fmt::Debug> fmt::Debug for BinaryHeapPlace<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("BinaryHeapPlace")
+ .field(&self.place)
+ .finish()
+ }
+}
+
#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
length: usize,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for Iter<'a, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_list().entries(self.clone()).finish()
+ }
+}
+
/// A mutable iterator over a BTreeMap's entries.
#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
pub struct IterMut<'a, K: 'a, V: 'a> {
range: RangeMut<'a, K, V>,
length: usize,
length: usize,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IntoIter<K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let range = Range {
+ front: self.front.reborrow(),
+ back: self.back.reborrow(),
+ };
+ f.debug_list().entries(range).finish()
+ }
+}
+
/// An iterator over a BTreeMap's keys.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Keys<'a, K: 'a, V: 'a> {
inner: Iter<'a, K, V>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for Keys<'a, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_list().entries(self.inner.clone()).finish()
+ }
+}
+
/// An iterator over a BTreeMap's values.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Values<'a, K: 'a, V: 'a> {
inner: Iter<'a, K, V>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for Values<'a, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_list().entries(self.inner.clone()).finish()
+ }
+}
+
/// A mutable iterator over a BTreeMap's values.
#[stable(feature = "map_values_mut", since = "1.10.0")]
+#[derive(Debug)]
pub struct ValuesMut<'a, K: 'a, V: 'a> {
inner: IterMut<'a, K, V>,
}
back: Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for Range<'a, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_list().entries(self.clone()).finish()
+ }
+}
+
/// A mutable iterator over a sub-range of BTreeMap's entries.
pub struct RangeMut<'a, K: 'a, V: 'a> {
front: Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>,
_marker: PhantomData<&'a mut (K, V)>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for RangeMut<'a, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let range = Range {
+ front: self.front.reborrow(),
+ back: self.back.reborrow(),
+ };
+ f.debug_list().entries(range).finish()
+ }
+}
+
/// A view into a single entry in a map, which may either be vacant or occupied.
/// This enum is constructed from the [`entry`] method on [`BTreeMap`].
///
iter: Keys<'a, T, ()>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for Iter<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("Iter")
+ .field(&self.iter.clone())
+ .finish()
+ }
+}
+
/// An owning iterator over a `BTreeSet`'s items.
///
/// This structure is created by the `into_iter` method on [`BTreeSet`]
///
/// [`BTreeSet`]: struct.BTreeSet.html
#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
pub struct IntoIter<T> {
iter: ::btree_map::IntoIter<T, ()>,
}
///
/// [`BTreeSet`]: struct.BTreeSet.html
/// [`range`]: struct.BTreeSet.html#method.range
+#[derive(Debug)]
pub struct Range<'a, T: 'a> {
iter: ::btree_map::Range<'a, T, ()>,
}
b: Peekable<Iter<'a, T>>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for Difference<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("Difference")
+ .field(&self.clone())
+ .finish()
+ }
+}
+
/// A lazy iterator producing elements in the set symmetric difference (in-order).
///
/// This structure is created by the [`symmetric_difference`] method on
b: Peekable<Iter<'a, T>>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for SymmetricDifference<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("SymmetricDifference")
+ .field(&self.clone())
+ .finish()
+ }
+}
+
/// A lazy iterator producing elements in the set intersection (in-order).
///
/// This structure is created by the [`intersection`] method on [`BTreeSet`].
b: Peekable<Iter<'a, T>>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for Intersection<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("Intersection")
+ .field(&self.clone())
+ .finish()
+ }
+}
+
/// A lazy iterator producing elements in the set union (in-order).
///
/// This structure is created by the [`union`] method on [`BTreeSet`].
b: Peekable<Iter<'a, T>>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for Union<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("Union")
+ .field(&self.clone())
+ .finish()
+ }
+}
+
impl<T: Ord> BTreeSet<T> {
/// Makes a new `BTreeSet` with a reasonable choice of B.
///
marker: marker::PhantomData<E>,
}
+impl<E: fmt::Debug> fmt::Debug for Iter<E> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("Iter")
+ .field(&self.clone())
+ .finish()
+ }
+}
+
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
impl<E> Clone for Iter<E> {
fn clone(&self) -> Iter<E> {
/// [format!]: ../macro.format.html
#[stable(feature = "rust1", since = "1.0.0")]
pub fn format(args: Arguments) -> string::String {
- let mut output = string::String::new();
+ let capacity = args.estimated_capacity();
+ let mut output = string::String::with_capacity(capacity);
let _ = output.write_fmt(args);
output
}
#![cfg_attr(test, allow(deprecated))] // rand
#![deny(warnings)]
+#![deny(missing_debug_implementations)]
#![feature(alloc)]
#![feature(allow_internal_unstable)]
marker: PhantomData<&'a Node<T>>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for Iter<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("Iter")
+ .field(&self.clone())
+ .finish()
+ }
+}
+
// FIXME #19839: deriving is too aggressive on the bounds (T doesn't need to be Clone).
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Clone for Iter<'a, T> {
len: usize,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for IterMut<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("IterMut")
+ .field(self.clone())
+ .finish()
+ }
+}
+
/// An iterator over the elements of a `LinkedList`.
#[derive(Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
list: LinkedList<T>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("IntoIter")
+ .field(self.clone())
+ .finish()
+ }
+}
+
impl<T> Node<T> {
fn new(element: T) -> Self {
Node {
node: IntermediateBox<Node<T>>,
}
+#[unstable(feature = "collection_placement",
+ reason = "struct name and placement protocol are subject to change",
+ issue = "30172")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for FrontPlace<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("FrontPlace")
+ .field(self.clone())
+ .finish()
+ }
+}
+
#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
node: IntermediateBox<Node<T>>,
}
+#[unstable(feature = "collection_placement",
+ reason = "struct name and placement protocol are subject to change",
+ issue = "30172")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for BackPlace<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("BackPlace")
+ .field(self.clone())
+ .finish()
+ }
+}
+
#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
#![cfg_attr(test, allow(unused_imports, dead_code))]
use alloc::boxed::Box;
-use core::cmp::Ordering::{self, Greater};
+use core::cmp::Ordering::{self, Less};
use core::mem::size_of;
use core::mem;
use core::ptr;
pub fn sort(&mut self)
where T: Ord
{
- self.sort_by(|a, b| a.cmp(b))
+ merge_sort(self, |a, b| a.lt(b));
}
/// Sorts the slice using `f` to extract a key to compare elements by.
pub fn sort_by_key<B, F>(&mut self, mut f: F)
where F: FnMut(&T) -> B, B: Ord
{
- self.sort_by(|a, b| f(a).cmp(&f(b)))
+ merge_sort(self, |a, b| f(a).lt(&f(b)));
}
/// Sorts the slice using `compare` to compare elements.
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn sort_by<F>(&mut self, compare: F)
+ pub fn sort_by<F>(&mut self, mut compare: F)
where F: FnMut(&T, &T) -> Ordering
{
- merge_sort(self, compare)
+ merge_sort(self, |a, b| compare(a, b) == Less);
}
/// Copies the elements from `src` into `self`.
/// Inserts `v[0]` into pre-sorted sequence `v[1..]` so that whole `v[..]` becomes sorted.
///
/// This is the integral subroutine of insertion sort.
-fn insert_head<T, F>(v: &mut [T], compare: &mut F)
- where F: FnMut(&T, &T) -> Ordering
+fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
+ where F: FnMut(&T, &T) -> bool
{
- if v.len() >= 2 && compare(&v[0], &v[1]) == Greater {
+ if v.len() >= 2 && is_less(&v[1], &v[0]) {
unsafe {
// There are three ways to implement insertion here:
//
// Intermediate state of the insertion process is always tracked by `hole`, which
// serves two purposes:
- // 1. Protects integrity of `v` from panics in `compare`.
+ // 1. Protects integrity of `v` from panics in `is_less`.
// 2. Fills the remaining hole in `v` in the end.
//
// Panic safety:
//
- // If `compare` panics at any point during the process, `hole` will get dropped and
+ // If `is_less` panics at any point during the process, `hole` will get dropped and
// fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it
// initially held exactly once.
let mut hole = InsertionHole {
ptr::copy_nonoverlapping(&v[1], &mut v[0], 1);
for i in 2..v.len() {
- if compare(&tmp.value, &v[i]) != Greater {
+ if !is_less(&v[i], &tmp.value) {
break;
}
ptr::copy_nonoverlapping(&v[i], &mut v[i - 1], 1);
///
/// The two slices must be non-empty and `mid` must be in bounds. Buffer `buf` must be long enough
/// to hold a copy of the shorter slice. Also, `T` must not be a zero-sized type.
-unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, compare: &mut F)
- where F: FnMut(&T, &T) -> Ordering
+unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F)
+ where F: FnMut(&T, &T) -> bool
{
let len = v.len();
let v = v.as_mut_ptr();
// hole in `v`.
//
// Intermediate state of the process is always tracked by `hole`, which serves two purposes:
- // 1. Protects integrity of `v` from panics in `compare`.
+ // 1. Protects integrity of `v` from panics in `is_less`.
// 2. Fills the remaining hole in `v` if the longer run gets consumed first.
//
// Panic safety:
//
- // If `compare` panics at any point during the process, `hole` will get dropped and fill the
+ // If `is_less` panics at any point during the process, `hole` will get dropped and fill the
// hole in `v` with the unconsumed range in `buf`, thus ensuring that `v` still holds every
// object it initially held exactly once.
let mut hole;
while *left < hole.end && right < v_end {
// Consume the lesser side.
// If equal, prefer the left run to maintain stability.
- let to_copy = if compare(&**left, &*right) == Greater {
+ let to_copy = if is_less(&*right, &**left) {
get_and_increment(&mut right)
} else {
get_and_increment(left)
while v < *left && buf < *right {
// Consume the greater side.
// If equal, prefer the right run to maintain stability.
- let to_copy = if compare(&*left.offset(-1), &*right.offset(-1)) == Greater {
+ let to_copy = if is_less(&*right.offset(-1), &*left.offset(-1)) {
decrement_and_get(left)
} else {
decrement_and_get(right)
/// 2. for every `i` in `2..runs.len()`: `runs[i - 2].len > runs[i - 1].len + runs[i].len`
///
/// The invariants ensure that the total running time is `O(n log n)` worst-case.
-fn merge_sort<T, F>(v: &mut [T], mut compare: F)
- where F: FnMut(&T, &T) -> Ordering
+fn merge_sort<T, F>(v: &mut [T], mut is_less: F)
+ where F: FnMut(&T, &T) -> bool
{
// Sorting has no meaningful behavior on zero-sized types.
if size_of::<T>() == 0 {
//
// Short runs are extended using insertion sort to span at least `min_run` elements, in order
// to improve performance.
- let (max_insertion, min_run) = if size_of::<T>() <= 16 {
+ let (max_insertion, min_run) = if size_of::<T>() <= 2 * mem::size_of::<usize>() {
(64, 32)
} else {
(32, 16)
if len <= max_insertion {
if len >= 2 {
for i in (0..len-1).rev() {
- insert_head(&mut v[i..], &mut compare);
+ insert_head(&mut v[i..], &mut is_less);
}
}
return;
// Allocate a buffer to use as scratch memory. We keep the length 0 so we can keep in it
// shallow copies of the contents of `v` without risking the dtors running on copies if
- // `compare` panics. When merging two sorted runs, this buffer holds a copy of the shorter run,
+ // `is_less` panics. When merging two sorted runs, this buffer holds a copy of the shorter run,
// which will always have length at most `len / 2`.
let mut buf = Vec::with_capacity(len / 2);
let mut start = end - 1;
if start > 0 {
start -= 1;
- if compare(&v[start], &v[start + 1]) == Greater {
- while start > 0 && compare(&v[start - 1], &v[start]) == Greater {
- start -= 1;
- }
- v[start..end].reverse();
- } else {
- while start > 0 && compare(&v[start - 1], &v[start]) != Greater {
- start -= 1;
+ unsafe {
+ if is_less(v.get_unchecked(start + 1), v.get_unchecked(start)) {
+ while start > 0 && is_less(v.get_unchecked(start),
+ v.get_unchecked(start - 1)) {
+ start -= 1;
+ }
+ v[start..end].reverse();
+ } else {
+ while start > 0 && !is_less(v.get_unchecked(start),
+ v.get_unchecked(start - 1)) {
+ start -= 1;
+ }
}
}
}
// merge sort on short sequences, so this significantly improves performance.
while start > 0 && end - start < min_run {
start -= 1;
- insert_head(&mut v[start..end], &mut compare);
+ insert_head(&mut v[start..end], &mut is_less);
}
// Push this run onto the stack.
let right = runs[r];
unsafe {
merge(&mut v[left.start .. right.start + right.len], left.len, buf.as_mut_ptr(),
- &mut compare);
+ &mut is_less);
}
runs[r] = Run {
start: left.start,
// It's cleaner to just turn off the unused_imports warning than to fix them.
#![allow(unused_imports)]
+use core::fmt;
use core::str as core_str;
use core::str::pattern::Pattern;
use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
encoder: Utf16Encoder<Chars<'a>>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a> fmt::Debug for EncodeUtf16<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.pad("EncodeUtf16 { .. }")
+ }
+}
+
#[stable(feature = "encode_utf16", since = "1.8.0")]
impl<'a> Iterator for EncodeUtf16<'a> {
type Item = u16;
}
}
+#[stable(feature = "cow_str_to_string_specialization", since = "1.17.0")]
+impl<'a> ToString for Cow<'a, str> {
+ #[inline]
+ fn to_string(&self) -> String {
+ self[..].to_owned()
+ }
+}
+
+#[stable(feature = "string_to_string_specialization", since = "1.17.0")]
+impl ToString for String {
+ #[inline]
+ fn to_string(&self) -> String {
+ self.to_owned()
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<str> for String {
#[inline]
iter: Chars<'a>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a> fmt::Debug for Drain<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.pad("Drain { .. }")
+ }
+}
+
#[stable(feature = "drain", since = "1.6.0")]
unsafe impl<'a> Sync for Drain<'a> {}
#[stable(feature = "drain", since = "1.6.0")]
/// assert_eq!(into_iter.next().unwrap(), 'z');
/// ```
#[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")]
- pub fn as_mut_slice(&self) -> &mut [T] {
+ pub fn as_mut_slice(&mut self) -> &mut [T] {
unsafe {
slice::from_raw_parts_mut(self.ptr as *mut T, self.len())
}
vec: Shared<Vec<T>>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for Drain<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("Drain")
+ .field(&self.iter.as_slice())
+ .finish()
+ }
+}
+
#[stable(feature = "drain", since = "1.6.0")]
unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {}
#[stable(feature = "drain", since = "1.6.0")]
#[unstable(feature = "collection_placement",
reason = "struct name and placement protocol are subject to change",
issue = "30172")]
+#[derive(Debug)]
pub struct PlaceBack<'a, T: 'a> {
vec: &'a mut Vec<T>,
}
/// buf.push_back(3);
/// buf.push_back(4);
/// buf.push_back(5);
+ /// assert_eq!(buf, [3, 4, 5]);
/// buf.swap(0, 2);
- /// assert_eq!(buf[0], 5);
- /// assert_eq!(buf[2], 3);
+ /// assert_eq!(buf, [5, 4, 3]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn swap(&mut self, i: usize, j: usize) {
/// buf.push_back(5);
/// buf.push_back(10);
/// buf.push_back(15);
+ /// assert_eq!(buf, [5, 10, 15]);
/// buf.truncate(1);
- /// assert_eq!(buf.len(), 1);
- /// assert_eq!(Some(&5), buf.get(0));
+ /// assert_eq!(buf, [5]);
/// ```
#[stable(feature = "deque_extras", since = "1.16.0")]
pub fn truncate(&mut self, len: usize) {
/// use std::collections::VecDeque;
///
/// let mut v: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
- /// assert_eq!(vec![3].into_iter().collect::<VecDeque<_>>(), v.drain(2..).collect());
- /// assert_eq!(vec![1, 2].into_iter().collect::<VecDeque<_>>(), v);
+ /// let drained = v.drain(2..).collect::<VecDeque<_>>();
+ /// assert_eq!(drained, [3]);
+ /// assert_eq!(v, [1, 2]);
///
/// // A full range clears all contents
/// v.drain(..);
/// buf.push_back(1);
/// buf.push_back(2);
/// buf.push_back(3);
+ /// assert_eq!(buf, [1, 2, 3]);
///
/// assert_eq!(buf.swap_remove_back(0), Some(1));
- /// assert_eq!(buf.len(), 2);
- /// assert_eq!(buf[0], 3);
- /// assert_eq!(buf[1], 2);
+ /// assert_eq!(buf, [3, 2]);
/// ```
#[stable(feature = "deque_extras_15", since = "1.5.0")]
pub fn swap_remove_back(&mut self, index: usize) -> Option<T> {
/// buf.push_back(1);
/// buf.push_back(2);
/// buf.push_back(3);
+ /// assert_eq!(buf, [1, 2, 3]);
///
/// assert_eq!(buf.swap_remove_front(2), Some(3));
- /// assert_eq!(buf.len(), 2);
- /// assert_eq!(buf[0], 2);
- /// assert_eq!(buf[1], 1);
+ /// assert_eq!(buf, [2, 1]);
/// ```
#[stable(feature = "deque_extras_15", since = "1.5.0")]
pub fn swap_remove_front(&mut self, index: usize) -> Option<T> {
/// vec_deque.push_back('a');
/// vec_deque.push_back('b');
/// vec_deque.push_back('c');
+ /// assert_eq!(vec_deque, &['a', 'b', 'c']);
///
/// vec_deque.insert(1, 'd');
- ///
- /// let vec = vec_deque.into_iter().collect::<Vec<_>>();
- /// assert_eq!(vec, ['a', 'd', 'b', 'c']);
+ /// assert_eq!(vec_deque, &['a', 'd', 'b', 'c']);
/// ```
#[stable(feature = "deque_extras_15", since = "1.5.0")]
pub fn insert(&mut self, index: usize, value: T) {
/// buf.push_back(1);
/// buf.push_back(2);
/// buf.push_back(3);
+ /// assert_eq!(buf, [1, 2, 3]);
///
/// assert_eq!(buf.remove(1), Some(2));
- /// assert_eq!(buf.get(1), Some(&3));
+ /// assert_eq!(buf, [1, 3]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove(&mut self, index: usize) -> Option<T> {
///
/// let mut buf: VecDeque<_> = vec![1,2,3].into_iter().collect();
/// let buf2 = buf.split_off(1);
- /// // buf = [1], buf2 = [2, 3]
- /// assert_eq!(buf.len(), 1);
- /// assert_eq!(buf2.len(), 2);
+ /// assert_eq!(buf, [1]);
+ /// assert_eq!(buf2, [2, 3]);
/// ```
#[inline]
#[stable(feature = "split_off", since = "1.4.0")]
/// ```
/// use std::collections::VecDeque;
///
- /// let mut buf: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
- /// let mut buf2: VecDeque<_> = vec![4, 5, 6].into_iter().collect();
+ /// let mut buf: VecDeque<_> = vec![1, 2].into_iter().collect();
+ /// let mut buf2: VecDeque<_> = vec![3, 4].into_iter().collect();
/// buf.append(&mut buf2);
- /// assert_eq!(buf.len(), 6);
- /// assert_eq!(buf2.len(), 0);
+ /// assert_eq!(buf, [1, 2, 3, 4]);
+ /// assert_eq!(buf2, []);
/// ```
#[inline]
#[stable(feature = "append", since = "1.4.0")]
/// let mut buf = VecDeque::new();
/// buf.extend(1..5);
/// buf.retain(|&x| x%2 == 0);
- ///
- /// let v: Vec<_> = buf.into_iter().collect();
- /// assert_eq!(&v[..], &[2, 4]);
+ /// assert_eq!(buf, [2, 4]);
/// ```
#[stable(feature = "vec_deque_retain", since = "1.4.0")]
pub fn retain<F>(&mut self, mut f: F)
/// buf.push_back(5);
/// buf.push_back(10);
/// buf.push_back(15);
+ /// assert_eq!(buf, [5, 10, 15]);
+ ///
/// buf.resize(2, 0);
- /// buf.resize(6, 20);
- /// for (a, b) in [5, 10, 20, 20, 20, 20].iter().zip(&buf) {
- /// assert_eq!(a, b);
- /// }
+ /// assert_eq!(buf, [5, 10]);
+ ///
+ /// buf.resize(5, 20);
+ /// assert_eq!(buf, [5, 10, 20, 20, 20]);
/// ```
#[stable(feature = "deque_extras", since = "1.16.0")]
pub fn resize(&mut self, new_len: usize, value: T) {
head: usize,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for Iter<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("Iter")
+ .field(&self.clone())
+ .finish()
+ }
+}
+
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Clone for Iter<'a, T> {
head: usize,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for IterMut<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("IterMut")
+ .field(&self.clone())
+ .finish()
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
inner: VecDeque<T>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("IntoIter")
+ .field(&self.clone())
+ .finish()
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Iterator for IntoIter<T> {
type Item = T;
deque: Shared<VecDeque<T>>,
}
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for Drain<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("Drain")
+ .field(&self.clone())
+ .finish()
+ }
+}
+
#[stable(feature = "drain", since = "1.6.0")]
unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {}
#[stable(feature = "drain", since = "1.6.0")]
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Eq> Eq for VecDeque<A> {}
+macro_rules! __impl_slice_eq1 {
+ ($Lhs: ty, $Rhs: ty) => {
+ __impl_slice_eq1! { $Lhs, $Rhs, Sized }
+ };
+ ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
+ #[stable(feature = "vec-deque-partial-eq-slice", since = "1.16.0")]
+ impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
+ fn eq(&self, other: &$Rhs) -> bool {
+ if self.len() != other.len() {
+ return false;
+ }
+ let (sa, sb) = self.as_slices();
+ let (oa, ob) = other[..].split_at(sa.len());
+ sa == oa && sb == ob
+ }
+ }
+ }
+}
+
+__impl_slice_eq1! { VecDeque<A>, Vec<B> }
+__impl_slice_eq1! { VecDeque<A>, &'b [B] }
+__impl_slice_eq1! { VecDeque<A>, &'b mut [B] }
+
+macro_rules! array_impls {
+ ($($N: expr)+) => {
+ $(
+ __impl_slice_eq1! { VecDeque<A>, [B; $N] }
+ __impl_slice_eq1! { VecDeque<A>, &'b [B; $N] }
+ __impl_slice_eq1! { VecDeque<A>, &'b mut [B; $N] }
+ )+
+ }
+}
+
+array_impls! {
+ 0 1 2 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28 29
+ 30 31 32
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: PartialOrd> PartialOrd for VecDeque<A> {
fn partial_cmp(&self, other: &VecDeque<A>) -> Option<Ordering> {
let final_len = usable_cap / 2;
for len in 0..final_len {
- let expected = if back {
+ let expected: VecDeque<_> = if back {
(0..len).collect()
} else {
(0..len).rev().collect()
// len is the length *after* insertion
for len in 1..cap {
// 0, 1, 2, .., len - 1
- let expected = (0..).take(len).collect();
+ let expected = (0..).take(len).collect::<VecDeque<_>>();
for tail_pos in 0..cap {
for to_insert in 0..len {
tester.tail = tail_pos;
// len is the length *after* removal
for len in 0..cap - 1 {
// 0, 1, 2, .., len - 1
- let expected = (0..).take(len).collect();
+ let expected = (0..).take(len).collect::<VecDeque<_>>();
for tail_pos in 0..cap {
for to_remove in 0..len + 1 {
tester.tail = tail_pos;
for len in 0..cap + 1 {
// 0, 1, 2, .., len - 1
- let expected = (0..).take(len).collect();
+ let expected = (0..).take(len).collect::<VecDeque<_>>();
for tail_pos in 0..max_cap + 1 {
tester.tail = tail_pos;
tester.head = tail_pos;
// index to split at
for at in 0..len + 1 {
// 0, 1, 2, .., at - 1 (may be empty)
- let expected_self = (0..).take(at).collect();
+ let expected_self = (0..).take(at).collect::<VecDeque<_>>();
// at, at + 1, .., len - 1 (may be empty)
- let expected_other = (at..).take(len - at).collect();
+ let expected_other = (at..).take(len - at).collect::<VecDeque<_>>();
for tail_pos in 0..cap {
tester.tail = tail_pos;
fn sort_large_random_expensive(b: &mut Bencher) {
let len = 10000;
b.iter(|| {
+ let mut v = gen_random(len);
let mut count = 0;
- let cmp = move |a: &u64, b: &u64| {
+ v.sort_by(|a: &u64, b: &u64| {
count += 1;
if count % 1_000_000_000 == 0 {
panic!("should not happen");
}
(*a as f64).cos().partial_cmp(&(*b as f64).cos()).unwrap()
- };
-
- let mut v = gen_random(len);
- v.sort_by(cmp);
-
+ });
black_box(count);
});
b.bytes = len as u64 * mem::size_of::<u64>() as u64;
assert!(e == VecDeque::new());
}
+#[test]
+fn test_partial_eq_array() {
+ let d = VecDeque::<char>::new();
+ assert!(d == []);
+
+ let mut d = VecDeque::new();
+ d.push_front('a');
+ assert!(d == ['a']);
+
+ let mut d = VecDeque::new();
+ d.push_back('a');
+ assert!(d == ['a']);
+
+ let mut d = VecDeque::new();
+ d.push_back('a');
+ d.push_back('b');
+ assert!(d == ['a', 'b']);
+}
+
#[test]
fn test_hash() {
let mut x = VecDeque::new();
sources.extend(&["x86_64/floatdidf.c", "x86_64/floatdisf.c", "x86_64/floatdixf.c"]);
}
} else {
- if !target.contains("freebsd") {
+ if !target.contains("freebsd") && !target.contains("netbsd") {
sources.extend(&["gcc_personality_v0.c"]);
}
#![feature(staged_api, core_intrinsics, repr_simd,
i128_type, core_float, abi_unadjusted, associated_consts)]
#![allow(non_camel_case_types, unused_variables, unused_imports)]
-#![cfg_attr(stage0, allow(dead_code))]
#[cfg(any(target_pointer_width="32", target_pointer_width="16", target_os="windows",
target_arch="mips64"))]
use core::intrinsics::unchecked_rem;
use core::ptr;
- // C API is expected to tolerate some amount of size mismatch in ABI. Hopefully the amount of
- // handling is sufficient for bootstrapping.
- #[cfg(stage0)]
- type u128_ = u64;
- #[cfg(stage0)]
- type i128_ = i64;
- #[cfg(not(stage0))]
- type u128_ = u128;
- #[cfg(not(stage0))]
- type i128_ = i128;
-
macro_rules! ashl {
($a:expr, $b:expr, $ty:ty) => {{
let (a, b) = ($a, $b);
}
#[export_name="__ashlti3"]
- pub extern "C" fn shl(a: u128_, b: u128_) -> u128_ {
- ashl!(a, b, u128_)
+ pub extern "C" fn shl(a: u128, b: u128) -> u128 {
+ ashl!(a, b, u128)
}
macro_rules! ashr {
}
#[export_name="__ashrti3"]
- pub extern "C" fn shr(a: i128_, b: i128_) -> i128_ {
- ashr!(a, b, i128_)
+ pub extern "C" fn shr(a: i128, b: i128) -> i128 {
+ ashr!(a, b, i128)
}
macro_rules! lshr {
#[export_name="__lshrti3"]
- pub extern "C" fn lshr(a: u128_, b: u128_) -> u128_ {
- lshr!(a, b, u128_)
- }
-
- #[cfg(stage0)]
- pub extern "C" fn u128_div_mod(n: u128_, d: u128_, rem: *mut u128_) -> u128_ {
- unsafe {
- if !rem.is_null() {
- *rem = unchecked_rem(n, d);
- }
- unchecked_div(n, d)
- }
+ pub extern "C" fn lshr(a: u128, b: u128) -> u128 {
+ lshr!(a, b, u128)
}
- #[cfg(not(stage0))]
- pub extern "C" fn u128_div_mod(n: u128_, d: u128_, rem: *mut u128_) -> u128_ {
+ pub extern "C" fn u128_div_mod(n: u128, d: u128, rem: *mut u128) -> u128 {
// Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide
unsafe {
// special cases, X is unknown, K != 0
}
}
- fn i128_mod(a: i128_, b: i128_) -> i128_ {
+ fn i128_mod(a: i128, b: i128) -> i128 {
let b = b.uabs();
let sa = a.signum();
let a = a.uabs();
unsafe {
let mut r = ::core::mem::zeroed();
u128_div_mod(a, b, &mut r);
- if sa == -1 { (r as i128_).unchecked_neg() } else { r as i128_ }
+ if sa == -1 { (r as i128).unchecked_neg() } else { r as i128 }
}
}
- fn i128_div(a: i128_, b: i128_) -> i128_ {
+ fn i128_div(a: i128, b: i128) -> i128 {
let sa = a.signum();
let sb = b.signum();
let a = a.uabs();
let b = b.uabs();
let sr = sa.wrapping_mul(sb); // sign of quotient
(if sr == -1 {
- (u128_div_mod(a, b, ptr::null_mut()) as i128_).unchecked_neg()
+ (u128_div_mod(a, b, ptr::null_mut()) as i128).unchecked_neg()
} else {
- u128_div_mod(a, b, ptr::null_mut()) as i128_
+ u128_div_mod(a, b, ptr::null_mut()) as i128
})
}
- #[cfg(stage0)]
- #[export_name="__udivti3"]
- pub extern "C" fn u128_div(a: u128_, b: u128_) -> u128_ {
- (a / b)
- }
-
macro_rules! mulo {
($a:expr, $b:expr, $o: expr, $ty: ty) => {{
let (a, b, overflow) = ($a, $b, $o);
fn high(self) -> Self::HighHalf;
fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self;
}
- impl LargeInt for u64 {
- type LowHalf = u32;
- type HighHalf = u32;
-
- fn low(self) -> u32 {
- self as u32
- }
- fn high(self) -> u32 {
- (self.wrapping_shr(32)) as u32
- }
- fn from_parts(low: u32, high: u32) -> u64 {
- low as u64 | (high as u64).wrapping_shl(32)
- }
- }
- impl LargeInt for i64 {
- type LowHalf = u32;
- type HighHalf = i32;
-
- fn low(self) -> u32 {
- self as u32
- }
- fn high(self) -> i32 {
- self.wrapping_shr(32) as i32
- }
- fn from_parts(low: u32, high: i32) -> i64 {
- u64::from_parts(low, high as u32) as i64
- }
- }
- #[cfg(not(stage0))]
impl LargeInt for u128 {
type LowHalf = u64;
type HighHalf = u64;
(high as u128).wrapping_shl(64) | low as u128
}
}
- #[cfg(not(stage0))]
impl LargeInt for i128 {
type LowHalf = u64;
type HighHalf = i64;
}}
}
- #[cfg(stage0)]
#[export_name="__multi3"]
- pub extern "C" fn u128_mul(a: i128_, b: i128_) -> i128_ {
- ((a as i64).wrapping_mul(b as i64) as i128_)
- }
-
- #[cfg(not(stage0))]
- #[export_name="__multi3"]
- pub extern "C" fn u128_mul(a: i128_, b: i128_) -> i128_ {
- mul!(a, b, i128_, i64)
+ pub extern "C" fn u128_mul(a: i128, b: i128) -> i128 {
+ mul!(a, b, i128, i64)
}
trait AbsExt: Sized {
- fn uabs(self) -> u128_ {
- self.iabs() as u128_
- }
- fn iabs(self) -> i128_;
- }
-
- #[cfg(stage0)]
- impl AbsExt for i128_ {
- fn iabs(self) -> i128_ {
- let s = self >> 63;
- ((self ^ s).wrapping_sub(s))
+ fn uabs(self) -> u128 {
+ self.iabs() as u128
}
+ fn iabs(self) -> i128;
}
- #[cfg(not(stage0))]
- impl AbsExt for i128_ {
- fn iabs(self) -> i128_ {
+ impl AbsExt for i128 {
+ fn iabs(self) -> i128 {
let s = self >> 127;
((self ^ s).wrapping_sub(s))
}
}
trait NegExt: Sized {
- fn unchecked_neg(self) -> i128_;
+ fn unchecked_neg(self) -> i128;
}
- impl NegExt for i128_ {
- fn unchecked_neg(self) -> i128_ {
+ impl NegExt for i128 {
+ fn unchecked_neg(self) -> i128 {
(!self).wrapping_add(1)
}
}
let exponent = $from.get_exponent();
let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
- if sign == -1.0 || exponent < 0 { return 0 as u128_; }
+ if sign == -1.0 || exponent < 0 { return 0 as u128; }
if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 {
- return !(0 as u128_);
+ return !(0 as u128);
}
(if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
(mantissa as $outty)
let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
- if exponent < 0 { return 0 as i128_; }
+ if exponent < 0 { return 0 as i128; }
if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 {
let ret = if sign > 0.0 { <$outty>::max_value() } else { <$outty>::min_value() };
return ret
}
- fn i128_as_f64(a: i128_) -> f64 {
+ fn i128_as_f64(a: i128) -> f64 {
match a.signum() {
1 => u128_as_f64(a.uabs()),
0 => 0.0,
}
}
- fn i128_as_f32(a: i128_) -> f32 {
+ fn i128_as_f32(a: i128) -> f32 {
match a.signum() {
1 => u128_as_f32(a.uabs()),
0 => 0.0,
}
}
- fn u128_as_f64(mut a: u128_) -> f64 {
+ fn u128_as_f64(mut a: u128) -> f64 {
use ::core::f64::MANTISSA_DIGITS;
if a == 0 { return 0.0; }
let sd = 128u32.wrapping_sub(a.leading_zeros());
const MD1 : u32 = MANTISSA_DIGITS + 1;
const MD2 : u32 = MANTISSA_DIGITS + 2;
- // SNAP: replace this with !0u128
- let negn :u128_ = !0;
+ let negn = !0u128;
if sd > MANTISSA_DIGITS {
a = match sd {
MD2 => a,
_ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) |
(if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2)
- .wrapping_sub(sd as u128_))) == 0 { 0 } else { 1 })
+ .wrapping_sub(sd as u128))) == 0 { 0 } else { 1 })
};
a |= if (a & 4) == 0 { 0 } else { 1 };
a = a.wrapping_add(1);
}
}
- fn u128_as_f32(mut a: u128_) -> f32 {
+ fn u128_as_f32(mut a: u128) -> f32 {
use ::core::f32::MANTISSA_DIGITS;
if a == 0 { return 0.0; }
let sd = 128u32.wrapping_sub(a.leading_zeros());
const MD1 : u32 = MANTISSA_DIGITS + 1;
const MD2 : u32 = MANTISSA_DIGITS + 2;
- // SNAP: replace this with !0u128
- let negn :u128_ = !0;
+ let negn = !0u128;
if sd > MANTISSA_DIGITS {
a = match sd {
MD2 => a,
_ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) |
(if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2)
- .wrapping_sub(sd as u128_))) == 0 { 0 } else { 1 })
+ .wrapping_sub(sd as u128))) == 0 { 0 } else { 1 })
};
a |= if (a & 4) == 0 { 0 } else { 1 };
a = a.wrapping_add(1);
macro_rules! why_are_abi_strings_checked_by_parser { ($cret:ty, $conv:expr, $unadj:tt) => {
mod imp {
- use super::{i128_, u128_, LargeInt, FloatStuff, NegExt, AbsExt};
+ use super::{LargeInt, FloatStuff, NegExt, AbsExt};
use super::{i128_as_f64, i128_as_f32, u128_as_f64, u128_as_f32,
i128_div, i128_mod, u128_div_mod, unchecked_div, ptr};
// For x64
// aka.
// define i128 @__muloti4(i128, i128, i32*)
#[export_name="__muloti4"]
- pub unsafe extern $unadj fn i128_mul_oflow(a: i128_, b: i128_, o: *mut i32) -> i128_ {
- mulo!(a, b, o, i128_)
+ pub unsafe extern $unadj fn i128_mul_oflow(a: i128, b: i128, o: *mut i32) -> i128 {
+ mulo!(a, b, o, i128)
}
// For x64
// aka.
// define double @__muloti4(i128)
#[export_name="__floattidf"]
- pub extern $unadj fn i128_as_f64_(a: i128_) -> f64 {
+ pub extern $unadj fn i128_as_f64_(a: i128) -> f64 {
i128_as_f64(a)
}
#[export_name="__floattisf"]
- pub extern $unadj fn i128_as_f32_(a: i128_) -> f32 {
+ pub extern $unadj fn i128_as_f32_(a: i128) -> f32 {
i128_as_f32(a)
}
#[export_name="__floatuntidf"]
- pub extern $unadj fn u128_as_f64_(a: u128_) -> f64 {
+ pub extern $unadj fn u128_as_f64_(a: u128) -> f64 {
u128_as_f64(a)
}
#[export_name="__floatuntisf"]
- pub extern $unadj fn u128_as_f32_(a: u128_) -> f32 {
+ pub extern $unadj fn u128_as_f32_(a: u128) -> f32 {
u128_as_f32(a)
}
// aka.
// define i128 @stuff(double)
#[export_name="__fixunsdfti"]
- pub extern $unadj fn f64_as_u128(a: f64) -> u128_ {
- float_as_unsigned!(a, f64, u128_)
+ pub extern $unadj fn f64_as_u128(a: f64) -> u128 {
+ float_as_unsigned!(a, f64, u128)
}
#[export_name="__fixunssfti"]
- pub extern "unadjusted" fn f32_as_u128(a: f32) -> u128_ {
- float_as_unsigned!(a, f32, u128_)
+ pub extern $unadj fn f32_as_u128(a: f32) -> u128 {
+ float_as_unsigned!(a, f32, u128)
}
#[export_name="__fixdfti"]
- pub extern "unadjusted" fn f64_as_i128(a: f64) -> i128_ {
- float_as_signed!(a, f64, i128_)
+ pub extern $unadj fn f64_as_i128(a: f64) -> i128 {
+ float_as_signed!(a, f64, i128)
}
#[export_name="__fixsfti"]
- pub extern "unadjusted" fn f32_as_i128(a: f32) -> i128_ {
- float_as_signed!(a, f32, i128_)
+ pub extern $unadj fn f32_as_i128(a: f32) -> i128 {
+ float_as_signed!(a, f32, i128)
}
#[repr(simd)]
//
// That almost matches the C ABI, so we simply use the C ABI
#[export_name="__udivmodti4"]
- pub extern "C" fn u128_div_mod_(n: u128_, d: u128_, rem: *mut u128_) -> $cret {
+ pub extern "C" fn u128_div_mod_(n: u128, d: u128, rem: *mut u128) -> $cret {
let x = u128_div_mod(n, d, rem);
($conv)(x)
}
#[export_name="__udivti3"]
- pub extern "C" fn u128_div_(a: u128_, b: u128_) -> $cret {
+ pub extern "C" fn u128_div_(a: u128, b: u128) -> $cret {
let x = u128_div_mod(a, b, ptr::null_mut());
($conv)(x)
}
#[export_name="__umodti3"]
- pub extern "C" fn u128_mod_(a: u128_, b: u128_) -> $cret {
+ pub extern "C" fn u128_mod_(a: u128, b: u128) -> $cret {
unsafe {
let mut r = ::core::mem::zeroed();
u128_div_mod(a, b, &mut r);
}
#[export_name="__divti3"]
- pub extern "C" fn i128_div_(a: i128_, b: i128_) -> $cret {
+ pub extern "C" fn i128_div_(a: i128, b: i128) -> $cret {
let x = i128_div(a, b);
- ($conv)(x as u128_)
+ ($conv)(x as u128)
}
#[export_name="__modti3"]
- pub extern "C" fn i128_mod_(a: i128_, b: i128_) -> $cret {
+ pub extern "C" fn i128_mod_(a: i128, b: i128) -> $cret {
let x = i128_mod(a, b);
- ($conv)(x as u128_)
+ ($conv)(x as u128)
}
}
} }
// LLVM expectations for ABI on windows x64 are pure madness.
- #[cfg(not(stage0))]
#[cfg(all(windows, target_pointer_width="64"))]
why_are_abi_strings_checked_by_parser!(u64x2,
- |i: u128_| u64x2(i.low(), i.high()),
+ |i: u128| u64x2(i.low(), i.high()),
"unadjusted");
- #[cfg(not(stage0))]
#[cfg(not(all(windows, target_pointer_width="64")))]
- why_are_abi_strings_checked_by_parser!(u128_, |i|{ i }, "C");
-
- #[cfg(not(stage0))]
+ why_are_abi_strings_checked_by_parser!(u128, |i|{ i }, "C");
pub use self::imp::*;
}
name = "coretest"
path = "../libcoretest/lib.rs"
-# FIXME: need to extract benchmarks to a separate crate
-#[[bench]]
-#name = "coretest"
-#path = "../libcoretest/lib.rs"
+[[bench]]
+name = "corebench"
+path = "../libcore/bench/lib.rs"
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::any::*;
+use test::{Bencher, black_box};
+
+#[bench]
+fn bench_downcast_ref(b: &mut Bencher) {
+ b.iter(|| {
+ let mut x = 0;
+ let mut y = &mut x as &mut Any;
+ black_box(&mut y);
+ black_box(y.downcast_ref::<isize>() == Some(&0));
+ });
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod sip;
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(deprecated)]
+
+use core::hash::*;
+use test::{Bencher, black_box};
+
+fn hash_bytes<H: Hasher>(mut s: H, x: &[u8]) -> u64 {
+ Hasher::write(&mut s, x);
+ s.finish()
+}
+
+fn hash_with<H: Hasher, T: Hash>(mut st: H, x: &T) -> u64 {
+ x.hash(&mut st);
+ st.finish()
+}
+
+fn hash<T: Hash>(x: &T) -> u64 {
+ hash_with(SipHasher::new(), x)
+}
+
+#[bench]
+fn bench_str_under_8_bytes(b: &mut Bencher) {
+ let s = "foo";
+ b.iter(|| {
+ assert_eq!(hash(&s), 16262950014981195938);
+ })
+}
+
+#[bench]
+fn bench_str_of_8_bytes(b: &mut Bencher) {
+ let s = "foobar78";
+ b.iter(|| {
+ assert_eq!(hash(&s), 4898293253460910787);
+ })
+}
+
+#[bench]
+fn bench_str_over_8_bytes(b: &mut Bencher) {
+ let s = "foobarbaz0";
+ b.iter(|| {
+ assert_eq!(hash(&s), 10581415515220175264);
+ })
+}
+
+#[bench]
+fn bench_long_str(b: &mut Bencher) {
+ let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \
+incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \
+exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute \
+irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \
+pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \
+officia deserunt mollit anim id est laborum.";
+ b.iter(|| {
+ assert_eq!(hash(&s), 17717065544121360093);
+ })
+}
+
+#[bench]
+fn bench_u32(b: &mut Bencher) {
+ let u = 162629500u32;
+ let u = black_box(u);
+ b.iter(|| {
+ hash(&u)
+ });
+ b.bytes = 8;
+}
+
+#[bench]
+fn bench_u32_keyed(b: &mut Bencher) {
+ let u = 162629500u32;
+ let u = black_box(u);
+ let k1 = black_box(0x1);
+ let k2 = black_box(0x2);
+ b.iter(|| {
+ hash_with(SipHasher::new_with_keys(k1, k2), &u)
+ });
+ b.bytes = 8;
+}
+
+#[bench]
+fn bench_u64(b: &mut Bencher) {
+ let u = 16262950014981195938u64;
+ let u = black_box(u);
+ b.iter(|| {
+ hash(&u)
+ });
+ b.bytes = 8;
+}
+
+#[bench]
+fn bench_bytes_4(b: &mut Bencher) {
+ let data = black_box([b' '; 4]);
+ b.iter(|| {
+ hash_bytes(SipHasher::default(), &data)
+ });
+ b.bytes = 4;
+}
+
+#[bench]
+fn bench_bytes_7(b: &mut Bencher) {
+ let data = black_box([b' '; 7]);
+ b.iter(|| {
+ hash_bytes(SipHasher::default(), &data)
+ });
+ b.bytes = 7;
+}
+
+#[bench]
+fn bench_bytes_8(b: &mut Bencher) {
+ let data = black_box([b' '; 8]);
+ b.iter(|| {
+ hash_bytes(SipHasher::default(), &data)
+ });
+ b.bytes = 8;
+}
+
+#[bench]
+fn bench_bytes_a_16(b: &mut Bencher) {
+ let data = black_box([b' '; 16]);
+ b.iter(|| {
+ hash_bytes(SipHasher::default(), &data)
+ });
+ b.bytes = 16;
+}
+
+#[bench]
+fn bench_bytes_b_32(b: &mut Bencher) {
+ let data = black_box([b' '; 32]);
+ b.iter(|| {
+ hash_bytes(SipHasher::default(), &data)
+ });
+ b.bytes = 32;
+}
+
+#[bench]
+fn bench_bytes_c_128(b: &mut Bencher) {
+ let data = black_box([b' '; 128]);
+ b.iter(|| {
+ hash_bytes(SipHasher::default(), &data)
+ });
+ b.bytes = 128;
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::iter::*;
+use test::{Bencher, black_box};
+
+#[bench]
+fn bench_rposition(b: &mut Bencher) {
+ let it: Vec<usize> = (0..300).collect();
+ b.iter(|| {
+ it.iter().rposition(|&x| x <= 150);
+ });
+}
+
+#[bench]
+fn bench_skip_while(b: &mut Bencher) {
+ b.iter(|| {
+ let it = 0..100;
+ let mut sum = 0;
+ it.skip_while(|&x| { sum += x; sum < 4000 }).all(|_| true);
+ });
+}
+
+#[bench]
+fn bench_multiple_take(b: &mut Bencher) {
+ let mut it = (0..42).cycle();
+ b.iter(|| {
+ let n = it.next().unwrap();
+ for _ in 0..n {
+ it.clone().take(it.next().unwrap()).all(|_| true);
+ }
+ });
+}
+
+fn scatter(x: i32) -> i32 { (x * 31) % 127 }
+
+#[bench]
+fn bench_max_by_key(b: &mut Bencher) {
+ b.iter(|| {
+ let it = 0..100;
+ it.max_by_key(|&x| scatter(x))
+ })
+}
+
+// http://www.reddit.com/r/rust/comments/31syce/using_iterators_to_find_the_index_of_the_min_or/
+#[bench]
+fn bench_max_by_key2(b: &mut Bencher) {
+ fn max_index_iter(array: &[i32]) -> usize {
+ array.iter().enumerate().max_by_key(|&(_, item)| item).unwrap().0
+ }
+
+ let mut data = vec![0; 1638];
+ data[514] = 9999;
+
+ b.iter(|| max_index_iter(&data));
+}
+
+#[bench]
+fn bench_max(b: &mut Bencher) {
+ b.iter(|| {
+ let it = 0..100;
+ it.map(scatter).max()
+ })
+}
+
+pub fn copy_zip(xs: &[u8], ys: &mut [u8]) {
+ for (a, b) in ys.iter_mut().zip(xs) {
+ *a = *b;
+ }
+}
+
+pub fn add_zip(xs: &[f32], ys: &mut [f32]) {
+ for (a, b) in ys.iter_mut().zip(xs) {
+ *a += *b;
+ }
+}
+
+#[bench]
+fn bench_zip_copy(b: &mut Bencher) {
+ let source = vec![0u8; 16 * 1024];
+ let mut dst = black_box(vec![0u8; 16 * 1024]);
+ b.iter(|| {
+ copy_zip(&source, &mut dst)
+ })
+}
+
+#[bench]
+fn bench_zip_add(b: &mut Bencher) {
+ let source = vec![1.; 16 * 1024];
+ let mut dst = vec![0.; 16 * 1024];
+ b.iter(|| {
+ add_zip(&source, &mut dst)
+ });
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(warnings)]
+
+#![feature(flt2dec)]
+#![feature(slice_patterns)]
+#![feature(test)]
+
+extern crate core;
+extern crate test;
+
+mod any;
+mod hash;
+mod iter;
+mod mem;
+mod num;
+mod ops;
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use test::Bencher;
+
+// FIXME #13642 (these benchmarks should be in another place)
+// Completely miscellaneous language-construct benchmarks.
+// Static/dynamic method dispatch
+
+struct Struct {
+ field: isize
+}
+
+trait Trait {
+ fn method(&self) -> isize;
+}
+
+impl Trait for Struct {
+ fn method(&self) -> isize {
+ self.field
+ }
+}
+
+#[bench]
+fn trait_vtable_method_call(b: &mut Bencher) {
+ let s = Struct { field: 10 };
+ let t = &s as &Trait;
+ b.iter(|| {
+ t.method()
+ });
+}
+
+#[bench]
+fn trait_static_method_call(b: &mut Bencher) {
+ let s = Struct { field: 10 };
+ b.iter(|| {
+ s.method()
+ });
+}
+
+// Overhead of various match forms
+
+#[bench]
+fn match_option_some(b: &mut Bencher) {
+ let x = Some(10);
+ b.iter(|| {
+ match x {
+ Some(y) => y,
+ None => 11
+ }
+ });
+}
+
+#[bench]
+fn match_vec_pattern(b: &mut Bencher) {
+ let x = [1,2,3,4,5,6];
+ b.iter(|| {
+ match x {
+ [1,2,3,..] => 10,
+ _ => 11,
+ }
+ });
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::f64;
+use test::Bencher;
+
+#[bench]
+fn bench_0(b: &mut Bencher) {
+ b.iter(|| "0.0".parse::<f64>());
+}
+
+#[bench]
+fn bench_42(b: &mut Bencher) {
+ b.iter(|| "42".parse::<f64>());
+}
+
+#[bench]
+fn bench_huge_int(b: &mut Bencher) {
+ // 2^128 - 1
+ b.iter(|| "170141183460469231731687303715884105727".parse::<f64>());
+}
+
+#[bench]
+fn bench_short_decimal(b: &mut Bencher) {
+ b.iter(|| "1234.5678".parse::<f64>());
+}
+
+#[bench]
+fn bench_pi_long(b: &mut Bencher) {
+ b.iter(|| "3.14159265358979323846264338327950288".parse::<f64>());
+}
+
+#[bench]
+fn bench_pi_short(b: &mut Bencher) {
+ b.iter(|| "3.141592653589793".parse::<f64>())
+}
+
+#[bench]
+fn bench_1e150(b: &mut Bencher) {
+ b.iter(|| "1e150".parse::<f64>());
+}
+
+#[bench]
+fn bench_long_decimal_and_exp(b: &mut Bencher) {
+ b.iter(|| "727501488517303786137132964064381141071e-123".parse::<f64>());
+}
+
+#[bench]
+fn bench_min_subnormal(b: &mut Bencher) {
+ b.iter(|| "5e-324".parse::<f64>());
+}
+
+#[bench]
+fn bench_min_normal(b: &mut Bencher) {
+ b.iter(|| "2.2250738585072014e-308".parse::<f64>());
+}
+
+#[bench]
+fn bench_max(b: &mut Bencher) {
+ b.iter(|| "1.7976931348623157e308".parse::<f64>());
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod strategy {
+ mod dragon;
+ mod grisu;
+}
+
+use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded};
+use core::num::flt2dec::MAX_SIG_DIGITS;
+
+pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
+ match decode(v).1 {
+ FullDecoded::Finite(decoded) => decoded,
+ full_decoded => panic!("expected finite, got {:?} instead", full_decoded)
+ }
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::{i16, f64};
+use super::super::*;
+use core::num::flt2dec::strategy::dragon::*;
+use test::Bencher;
+
+#[bench]
+fn bench_small_shortest(b: &mut Bencher) {
+ let decoded = decode_finite(3.141592f64);
+ let mut buf = [0; MAX_SIG_DIGITS];
+ b.iter(|| format_shortest(&decoded, &mut buf));
+}
+
+#[bench]
+fn bench_big_shortest(b: &mut Bencher) {
+ let decoded = decode_finite(f64::MAX);
+ let mut buf = [0; MAX_SIG_DIGITS];
+ b.iter(|| format_shortest(&decoded, &mut buf));
+}
+
+#[bench]
+fn bench_small_exact_3(b: &mut Bencher) {
+ let decoded = decode_finite(3.141592f64);
+ let mut buf = [0; 3];
+ b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
+}
+
+#[bench]
+fn bench_big_exact_3(b: &mut Bencher) {
+ let decoded = decode_finite(f64::MAX);
+ let mut buf = [0; 3];
+ b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
+}
+
+#[bench]
+fn bench_small_exact_12(b: &mut Bencher) {
+ let decoded = decode_finite(3.141592f64);
+ let mut buf = [0; 12];
+ b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
+}
+
+#[bench]
+fn bench_big_exact_12(b: &mut Bencher) {
+ let decoded = decode_finite(f64::MAX);
+ let mut buf = [0; 12];
+ b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
+}
+
+#[bench]
+fn bench_small_exact_inf(b: &mut Bencher) {
+ let decoded = decode_finite(3.141592f64);
+ let mut buf = [0; 1024];
+ b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
+}
+
+#[bench]
+fn bench_big_exact_inf(b: &mut Bencher) {
+ let decoded = decode_finite(f64::MAX);
+ let mut buf = [0; 1024];
+ b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::{i16, f64};
+use super::super::*;
+use core::num::flt2dec::strategy::grisu::*;
+use test::Bencher;
+
+pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
+ match decode(v).1 {
+ FullDecoded::Finite(decoded) => decoded,
+ full_decoded => panic!("expected finite, got {:?} instead", full_decoded)
+ }
+}
+
+#[bench]
+fn bench_small_shortest(b: &mut Bencher) {
+ let decoded = decode_finite(3.141592f64);
+ let mut buf = [0; MAX_SIG_DIGITS];
+ b.iter(|| format_shortest(&decoded, &mut buf));
+}
+
+#[bench]
+fn bench_big_shortest(b: &mut Bencher) {
+ let decoded = decode_finite(f64::MAX);
+ let mut buf = [0; MAX_SIG_DIGITS];
+ b.iter(|| format_shortest(&decoded, &mut buf));
+}
+
+#[bench]
+fn bench_small_exact_3(b: &mut Bencher) {
+ let decoded = decode_finite(3.141592f64);
+ let mut buf = [0; 3];
+ b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
+}
+
+#[bench]
+fn bench_big_exact_3(b: &mut Bencher) {
+ let decoded = decode_finite(f64::MAX);
+ let mut buf = [0; 3];
+ b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
+}
+
+#[bench]
+fn bench_small_exact_12(b: &mut Bencher) {
+ let decoded = decode_finite(3.141592f64);
+ let mut buf = [0; 12];
+ b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
+}
+
+#[bench]
+fn bench_big_exact_12(b: &mut Bencher) {
+ let decoded = decode_finite(f64::MAX);
+ let mut buf = [0; 12];
+ b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
+}
+
+#[bench]
+fn bench_small_exact_inf(b: &mut Bencher) {
+ let decoded = decode_finite(3.141592f64);
+ let mut buf = [0; 1024];
+ b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
+}
+
+#[bench]
+fn bench_big_exact_inf(b: &mut Bencher) {
+ let decoded = decode_finite(f64::MAX);
+ let mut buf = [0; 1024];
+ b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod flt2dec;
+mod dec2flt;
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::ops::*;
+use test::Bencher;
+
+// Overhead of dtors
+
+struct HasDtor {
+ _x: isize
+}
+
+impl Drop for HasDtor {
+ fn drop(&mut self) {
+ }
+}
+
+#[bench]
+fn alloc_obj_with_dtor(b: &mut Bencher) {
+ b.iter(|| {
+ HasDtor { _x : 10 };
+ })
+}
//! references. We say that `Cell<T>` and `RefCell<T>` provide 'interior mutability', in contrast
//! with typical Rust types that exhibit 'inherited mutability'.
//!
-//! Cell types come in two flavors: `Cell<T>` and `RefCell<T>`. `Cell<T>` provides `get` and `set`
-//! methods that change the interior value with a single method call. `Cell<T>` though is only
-//! compatible with types that implement `Copy`. For other types, one must use the `RefCell<T>`
-//! type, acquiring a write lock before mutating.
+//! Cell types come in two flavors: `Cell<T>` and `RefCell<T>`. `Cell<T>` implements interior
+//! mutability by moving values in and out of the `Cell<T>`. To use references instead of values,
+//! one must use the `RefCell<T>` type, acquiring a write lock before mutating. `Cell<T>` provides
+//! methods to retrieve and change the current interior value:
+//!
+//! - For types that implement `Copy`, the `get` method retrieves the current interior value.
+//! - For types that implement `Default`, the `take` method replaces the current interior value
+//! with `Default::default()` and returns the replaced value.
+//! - For all types, the `replace` method replaces the current interior value and returns the
+//! replaced value and the `into_inner` method consumes the `Cell<T>` and returns the interior
+//! value. Additionally, the `set` method replaces the interior value, dropping the replaced
+//! value.
//!
//! `RefCell<T>` uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can
//! claim temporary, exclusive, mutable access to the inner value. Borrows for `RefCell<T>`s are
use cmp::Ordering;
use fmt::{self, Debug, Display};
use marker::Unsize;
+use mem;
use ops::{Deref, DerefMut, CoerceUnsized};
-/// A mutable memory location that admits only `Copy` data.
+/// A mutable memory location.
///
/// See the [module-level documentation](index.html) for more.
#[stable(feature = "rust1", since = "1.0.0")]
}
impl<T:Copy> Cell<T> {
- /// Creates a new `Cell` containing the given value.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::cell::Cell;
- ///
- /// let c = Cell::new(5);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- pub const fn new(value: T) -> Cell<T> {
- Cell {
- value: UnsafeCell::new(value),
- }
- }
-
/// Returns a copy of the contained value.
///
/// # Examples
unsafe{ *self.value.get() }
}
- /// Sets the contained value.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::cell::Cell;
- ///
- /// let c = Cell::new(5);
- ///
- /// c.set(10);
- /// ```
- #[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn set(&self, value: T) {
- unsafe {
- *self.value.get() = value;
- }
- }
-
/// Returns a reference to the underlying `UnsafeCell`.
///
/// # Examples
}
}
+impl<T> Cell<T> {
+ /// Creates a new `Cell` containing the given value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cell::Cell;
+ ///
+ /// let c = Cell::new(5);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
+ pub const fn new(value: T) -> Cell<T> {
+ Cell {
+ value: UnsafeCell::new(value),
+ }
+ }
+
+ /// Sets the contained value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cell::Cell;
+ ///
+ /// let c = Cell::new(5);
+ ///
+ /// c.set(10);
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn set(&self, val: T) {
+ let old = self.replace(val);
+ drop(old);
+ }
+
+ /// Replaces the contained value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(move_cell)]
+ /// use std::cell::Cell;
+ ///
+ /// let c = Cell::new(5);
+ /// let old = c.replace(10);
+ ///
+ /// assert_eq!(5, old);
+ /// ```
+ #[unstable(feature = "move_cell", issue = "39264")]
+ pub fn replace(&self, val: T) -> T {
+ mem::replace(unsafe { &mut *self.value.get() }, val)
+ }
+
+ /// Unwraps the value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(move_cell)]
+ /// use std::cell::Cell;
+ ///
+ /// let c = Cell::new(5);
+ /// let five = c.into_inner();
+ ///
+ /// assert_eq!(five, 5);
+ /// ```
+ #[unstable(feature = "move_cell", issue = "39264")]
+ pub fn into_inner(self) -> T {
+ unsafe { self.value.into_inner() }
+ }
+}
+
+impl<T: Default> Cell<T> {
+ /// Takes the value of the cell, leaving `Default::default()` in its place.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(move_cell)]
+ /// use std::cell::Cell;
+ ///
+ /// let c = Cell::new(5);
+ /// let five = c.take();
+ ///
+ /// assert_eq!(five, 5);
+ /// assert_eq!(c.into_inner(), 0);
+ /// ```
+ #[unstable(feature = "move_cell", issue = "39264")]
+ pub fn take(&self) -> T {
+ self.replace(Default::default())
+ }
+}
+
#[unstable(feature = "coerce_unsized", issue = "27732")]
impl<T: CoerceUnsized<U>, U> CoerceUnsized<Cell<U>> for Cell<T> {}
#[unstable(feature = "fused", issue = "35602")]
impl FusedIterator for EscapeUnicode {}
-#[stable(feature = "char_struct_display", since = "1.17.0")]
+#[stable(feature = "char_struct_display", since = "1.16.0")]
impl fmt::Display for EscapeUnicode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for c in self.clone() {
#[unstable(feature = "fused", issue = "35602")]
impl FusedIterator for EscapeDefault {}
-#[stable(feature = "char_struct_display", since = "1.17.0")]
+#[stable(feature = "char_struct_display", since = "1.16.0")]
impl fmt::Display for EscapeDefault {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for c in self.clone() {
#[unstable(feature = "fused", issue = "35602")]
impl FusedIterator for EscapeDebug {}
-#[stable(feature = "char_struct_display", since = "1.17.0")]
+#[unstable(feature = "char_escape_debug", issue = "35068")]
impl fmt::Display for EscapeDebug {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
clone_impl! { i16 }
clone_impl! { i32 }
clone_impl! { i64 }
-#[cfg(not(stage0))]
clone_impl! { i128 }
clone_impl! { usize }
clone_impl! { u16 }
clone_impl! { u32 }
clone_impl! { u64 }
-#[cfg(not(stage0))]
clone_impl! { u128 }
clone_impl! { f32 }
}
partial_eq_impl! {
- bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64
+ bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64
}
- #[cfg(not(stage0))]
- partial_eq_impl! { u128 i128 }
macro_rules! eq_impl {
($($t:ty)*) => ($(
)*)
}
- eq_impl! { () bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
- #[cfg(not(stage0))]
- eq_impl! { u128 i128 }
+ eq_impl! { () bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
macro_rules! partial_ord_impl {
($($t:ty)*) => ($(
}
}
- ord_impl! { char usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
- #[cfg(not(stage0))]
- ord_impl! { u128 i128 }
+ ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
#[unstable(feature = "never_type_impls", issue = "35121")]
impl PartialEq for ! {
type Err;
/// Performs the conversion.
- fn try_from(T) -> Result<Self, Self::Err>;
+ fn try_from(value: T) -> Result<Self, Self::Err>;
}
////////////////////////////////////////////////////////////////////////////////
default_impl! { u16, 0 }
default_impl! { u32, 0 }
default_impl! { u64, 0 }
-#[cfg(not(stage0))]
default_impl! { u128, 0 }
default_impl! { isize, 0 }
default_impl! { i16, 0 }
default_impl! { i32, 0 }
default_impl! { i64, 0 }
-#[cfg(not(stage0))]
default_impl! { i128, 0 }
default_impl! { f32, 0.0f32 }
args: args
}
}
+
+ /// Estimates the length of the formatted text.
+ ///
+ /// This is intended to be used for setting initial `String` capacity
+ /// when using `format!`. Note: this is neither the lower nor upper bound.
+ #[doc(hidden)] #[inline]
+ #[unstable(feature = "fmt_internals", reason = "internal to format_args!",
+ issue = "0")]
+ pub fn estimated_capacity(&self) -> usize {
+ let pieces_length: usize = self.pieces.iter()
+ .map(|x| x.len()).sum();
+
+ if self.args.is_empty() {
+ pieces_length
+ } else if self.pieces[0] == "" && pieces_length < 16 {
+ // If the format string starts with an argument,
+ // don't preallocate anything, unless length
+ // of pieces is significant.
+ 0
+ } else {
+ // There are some arguments, so any additional push
+ // will reallocate the string. To avoid that,
+ // we're "pre-doubling" the capacity here.
+ pieces_length.checked_mul(2).unwrap_or(0)
+ }
+ }
}
/// This structure represents a safely precompiled version of a format string
fn to_u16(&self) -> u16;
fn to_u32(&self) -> u32;
fn to_u64(&self) -> u64;
- #[cfg(not(stage0))]
fn to_u128(&self) -> u128;
}
fn to_u16(&self) -> u16 { *self as u16 }
fn to_u32(&self) -> u32 { *self as u32 }
fn to_u64(&self) -> u64 { *self as u64 }
- #[cfg(not(stage0))]
fn to_u128(&self) -> u128 { *self as u128 }
})*)
}
-doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
-#[cfg(not(stage0))]
-doit! { i128 u128 }
+doit! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
/// A type that represents a specific radix
#[doc(hidden)]
integer! { i16, u16 }
integer! { i32, u32 }
integer! { i64, u64 }
-#[cfg(not(stage0))]
integer! { i128, u128 }
const DEC_DIGITS_LUT: &'static[u8] =
impl_Display!(i8, u8, i16, u16, i32, u32: to_u32);
impl_Display!(i64, u64: to_u64);
-#[cfg(not(stage0))]
impl_Display!(i128, u128: to_u128);
#[cfg(target_pointer_width = "16")]
impl_Display!(isize, usize: to_u16);
fn write_u64(&mut self, i: u64) {
self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
}
- #[cfg(not(stage0))]
/// Writes a single `u128` into this hasher.
#[inline]
#[unstable(feature = "i128", issue = "35118")]
fn write_i64(&mut self, i: i64) {
self.write_u64(i as u64)
}
- #[cfg(not(stage0))]
/// Writes a single `i128` into this hasher.
#[inline]
#[unstable(feature = "i128", issue = "35118")]
(i32, write_i32),
(i64, write_i64),
(isize, write_isize),
- }
- #[cfg(not(stage0))]
- impl_write! {
(u128, write_u128),
(i128, write_i128),
}
// based on "op T" where T is expected to be `Copy`able
macro_rules! forward_ref_unop {
(impl $imp:ident, $method:ident for $t:ty) => {
- #[stable(feature = "rust1", since = "1.0.0")]
+ forward_ref_unop!(impl $imp, $method for $t,
+ #[stable(feature = "rust1", since = "1.0.0")]);
+ };
+ (impl $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => {
+ #[$attr]
impl<'a> $imp for &'a $t {
type Output = <$t as $imp>::Output;
// based on "T op U" where T and U are expected to be `Copy`able
macro_rules! forward_ref_binop {
(impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
- #[stable(feature = "rust1", since = "1.0.0")]
+ forward_ref_binop!(impl $imp, $method for $t, $u,
+ #[stable(feature = "rust1", since = "1.0.0")]);
+ };
+ (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
+ #[$attr]
impl<'a> $imp<$u> for &'a $t {
type Output = <$t as $imp<$u>>::Output;
}
}
- #[stable(feature = "rust1", since = "1.0.0")]
+ #[$attr]
impl<'a> $imp<&'a $u> for $t {
type Output = <$t as $imp<$u>>::Output;
}
}
- #[stable(feature = "rust1", since = "1.0.0")]
+ #[$attr]
impl<'a, 'b> $imp<&'a $u> for &'b $t {
type Output = <$t as $imp<$u>>::Output;
#[inline]
fn next(&mut self) -> Option<I::Item> {
- for x in self.iter.by_ref() {
+ for x in &mut self.iter {
if (self.predicate)(&x) {
return Some(x);
}
let (_, upper) = self.iter.size_hint();
(0, upper) // can't know a lower bound, due to the predicate
}
+
+ // this special case allows the compiler to make `.filter(_).count()`
+ // branchless. Barring perfect branch prediction (which is unattainable in
+ // the general case), this will be much faster in >90% of cases (containing
+ // virtually all real workloads) and only a tiny bit slower in the rest.
+ //
+ // Having this specialization thus allows us to write `.filter(p).count()`
+ // where we would otherwise write `.map(|x| p(x) as usize).sum()`, which is
+ // less readable and also less backwards-compatible to Rust before 1.10.
+ //
+ // Using the branchless version will also simplify the LLVM byte code, thus
+ // leaving more budget for LLVM optimizations.
+ #[inline]
+ fn count(mut self) -> usize {
+ let mut count = 0;
+ for x in &mut self.iter {
+ count += (self.predicate)(&x) as usize;
+ }
+ count
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
// assume here that it is less than 64-bits.
#[cfg(not(target_pointer_width = "64"))]
step_impl_no_between!(u64 i64);
-#[cfg(not(stage0))]
step_impl_no_between!(u128 i128);
/// An adapter for stepping range iterators by a custom amount.
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn next_back(&mut self) -> Option<Self::Item>;
+
+ /// Searches for an element of an iterator from the right that satisfies a predicate.
+ ///
+ /// `rfind()` takes a closure that returns `true` or `false`. It applies
+ /// this closure to each element of the iterator, starting at the end, and if any
+ /// of them return `true`, then `rfind()` returns [`Some(element)`]. If they all return
+ /// `false`, it returns [`None`].
+ ///
+ /// `rfind()` is short-circuiting; in other words, it will stop processing
+ /// as soon as the closure returns `true`.
+ ///
+ /// Because `rfind()` takes a reference, and many iterators iterate over
+ /// references, this leads to a possibly confusing situation where the
+ /// argument is a double reference. You can see this effect in the
+ /// examples below, with `&&x`.
+ ///
+ /// [`Some(element)`]: ../../std/option/enum.Option.html#variant.Some
+ /// [`None`]: ../../std/option/enum.Option.html#variant.None
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(iter_rfind)]
+ ///
+ /// let a = [1, 2, 3];
+ ///
+ /// assert_eq!(a.iter().rfind(|&&x| x == 2), Some(&2));
+ ///
+ /// assert_eq!(a.iter().rfind(|&&x| x == 5), None);
+ /// ```
+ ///
+ /// Stopping at the first `true`:
+ ///
+ /// ```
+ /// #![feature(iter_rfind)]
+ ///
+ /// let a = [1, 2, 3];
+ ///
+ /// let mut iter = a.iter();
+ ///
+ /// assert_eq!(iter.rfind(|&&x| x == 2), Some(&2));
+ ///
+ /// // we can still use `iter`, as there are more elements.
+ /// assert_eq!(iter.next_back(), Some(&1));
+ /// ```
+ #[inline]
+ #[unstable(feature = "iter_rfind", issue = "39480")]
+ fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
+ Self: Sized,
+ P: FnMut(&Self::Item) -> bool
+ {
+ for x in self.by_ref().rev() {
+ if predicate(&x) { return Some(x) }
+ }
+ None
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
// NB: explicitly use Add and Mul here to inherit overflow checks
macro_rules! integer_sum_product {
- (@impls $zero:expr, $one:expr, $($a:ty)*) => ($(
- #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+ (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
+ #[$attr]
impl Sum for $a {
fn sum<I: Iterator<Item=$a>>(iter: I) -> $a {
iter.fold($zero, Add::add)
}
}
- #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+ #[$attr]
impl Product for $a {
fn product<I: Iterator<Item=$a>>(iter: I) -> $a {
iter.fold($one, Mul::mul)
}
}
- #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+ #[$attr]
impl<'a> Sum<&'a $a> for $a {
fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
iter.fold($zero, Add::add)
}
}
- #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+ #[$attr]
impl<'a> Product<&'a $a> for $a {
fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
iter.fold($one, Mul::mul)
}
)*);
($($a:ty)*) => (
- integer_sum_product!(@impls 0, 1, $($a)+);
- integer_sum_product!(@impls Wrapping(0), Wrapping(1), $(Wrapping<$a>)+);
+ integer_sum_product!(@impls 0, 1,
+ #[stable(feature = "iter_arith_traits", since = "1.12.0")],
+ $($a)+);
+ integer_sum_product!(@impls Wrapping(0), Wrapping(1),
+ #[stable(feature = "wrapping_iter_arith", since = "1.14.0")],
+ $(Wrapping<$a>)+);
);
}
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(never_type)]
-#![cfg_attr(not(stage0), feature(i128_type))]
+#![feature(i128_type)]
#![feature(prelude_import)]
#[prelude_import]
#[path = "num/i16.rs"] pub mod i16;
#[path = "num/i32.rs"] pub mod i32;
#[path = "num/i64.rs"] pub mod i64;
-
-// SNAP
-#[cfg(not(stage0))]
#[path = "num/i128.rs"] pub mod i128;
#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u16.rs"] pub mod u16;
#[path = "num/u32.rs"] pub mod u32;
#[path = "num/u64.rs"] pub mod u64;
-
-// SNAP
-#[cfg(not(stage0))]
#[path = "num/u128.rs"] pub mod u128;
#[path = "num/f32.rs"] pub mod f32;
unsafe impl Zeroable for u32 {}
unsafe impl Zeroable for i64 {}
unsafe impl Zeroable for u64 {}
-#[cfg(not(stage0))]
unsafe impl Zeroable for i128 {}
-#[cfg(not(stage0))]
unsafe impl Zeroable for u128 {}
/// A wrapper type for raw pointers and integers that will never be
macro_rules! int_module {
($T:ident) => (int_module!($T, #[stable(feature = "rust1", since = "1.0.0")]););
- ($T:ident, $($attr: tt)*) => (
+ ($T:ident, #[$attr:meta]) => (
/// The smallest value that can be represented by this integer type.
- $($attr)*
+ #[$attr]
pub const MIN: $T = $T::min_value();
/// The largest value that can be represented by this integer type.
- $($attr)*
+ #[$attr]
pub const MAX: $T = $T::max_value();
)
}
}
)*)
}
-zero_one_impl! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
-#[cfg(not(stage0))]
-zero_one_impl! { u128 i128 }
+zero_one_impl! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
macro_rules! zero_one_impl_float {
($($t:ty)*) => ($(
intrinsics::mul_with_overflow }
}
-// SNAP
-#[cfg(not(stage0))]
#[lang = "i128"]
impl i128 {
int_impl! { i128, u128, 128,
intrinsics::mul_with_overflow }
}
-// SNAP
-#[cfg(not(stage0))]
#[lang = "u128"]
impl u128 {
uint_impl! { u128, 128,
}
)*}
}
-from_str_radix_int_impl! { isize i8 i16 i32 i64 usize u8 u16 u32 u64 }
-#[cfg(not(stage0))]
-from_str_radix_int_impl! { u128 i128 }
+from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 }
/// The error type returned when a checked integral type conversion fails.
#[unstable(feature = "try_from", issue = "33417")]
)*}
}
-#[cfg(stage0)]
-same_sign_try_from_int_impl!(u64, u8, u8, u16, u32, u64, usize);
-#[cfg(stage0)]
-same_sign_try_from_int_impl!(i64, i8, i8, i16, i32, i64, isize);
-#[cfg(stage0)]
-same_sign_try_from_int_impl!(u64, u16, u8, u16, u32, u64, usize);
-#[cfg(stage0)]
-same_sign_try_from_int_impl!(i64, i16, i8, i16, i32, i64, isize);
-#[cfg(stage0)]
-same_sign_try_from_int_impl!(u64, u32, u8, u16, u32, u64, usize);
-#[cfg(stage0)]
-same_sign_try_from_int_impl!(i64, i32, i8, i16, i32, i64, isize);
-#[cfg(stage0)]
-same_sign_try_from_int_impl!(u64, u64, u8, u16, u32, u64, usize);
-#[cfg(stage0)]
-same_sign_try_from_int_impl!(i64, i64, i8, i16, i32, i64, isize);
-#[cfg(stage0)]
-same_sign_try_from_int_impl!(u64, usize, u8, u16, u32, u64, usize);
-#[cfg(stage0)]
-same_sign_try_from_int_impl!(i64, isize, i8, i16, i32, i64, isize);
-
-#[cfg(not(stage0))]
same_sign_try_from_int_impl!(u128, u8, u8, u16, u32, u64, u128, usize);
-#[cfg(not(stage0))]
same_sign_try_from_int_impl!(i128, i8, i8, i16, i32, i64, i128, isize);
-#[cfg(not(stage0))]
same_sign_try_from_int_impl!(u128, u16, u8, u16, u32, u64, u128, usize);
-#[cfg(not(stage0))]
same_sign_try_from_int_impl!(i128, i16, i8, i16, i32, i64, i128, isize);
-#[cfg(not(stage0))]
same_sign_try_from_int_impl!(u128, u32, u8, u16, u32, u64, u128, usize);
-#[cfg(not(stage0))]
same_sign_try_from_int_impl!(i128, i32, i8, i16, i32, i64, i128, isize);
-#[cfg(not(stage0))]
same_sign_try_from_int_impl!(u128, u64, u8, u16, u32, u64, u128, usize);
-#[cfg(not(stage0))]
same_sign_try_from_int_impl!(i128, i64, i8, i16, i32, i64, i128, isize);
-#[cfg(not(stage0))]
same_sign_try_from_int_impl!(u128, u128, u8, u16, u32, u64, u128, usize);
-#[cfg(not(stage0))]
same_sign_try_from_int_impl!(i128, i128, i8, i16, i32, i64, i128, isize);
-#[cfg(not(stage0))]
same_sign_try_from_int_impl!(u128, usize, u8, u16, u32, u64, u128, usize);
-#[cfg(not(stage0))]
same_sign_try_from_int_impl!(i128, isize, i8, i16, i32, i64, i128, isize);
macro_rules! cross_sign_from_int_impl {
type Err = TryFromIntError;
fn try_from(u: $unsigned) -> Result<$signed, TryFromIntError> {
- let max = <$signed as FromStrRadixHelper>::max_value() as u64;
- if u as u64 > max {
+ let max = <$signed as FromStrRadixHelper>::max_value() as u128;
+ if u as u128 > max {
Err(TryFromIntError(()))
} else {
Ok(u as $signed)
type Err = TryFromIntError;
fn try_from(u: $signed) -> Result<$unsigned, TryFromIntError> {
- let max = <$unsigned as FromStrRadixHelper>::max_value() as u64;
- if u < 0 || u as u64 > max {
+ let max = <$unsigned as FromStrRadixHelper>::max_value() as u128;
+ if u < 0 || u as u128 > max {
Err(TryFromIntError(()))
} else {
Ok(u as $unsigned)
)*}
}
-#[cfg(stage0)]
-cross_sign_from_int_impl!(u8, i8, i16, i32, i64, isize);
-#[cfg(stage0)]
-cross_sign_from_int_impl!(u16, i8, i16, i32, i64, isize);
-#[cfg(stage0)]
-cross_sign_from_int_impl!(u32, i8, i16, i32, i64, isize);
-#[cfg(stage0)]
-cross_sign_from_int_impl!(u64, i8, i16, i32, i64, isize);
-#[cfg(stage0)]
-cross_sign_from_int_impl!(usize, i8, i16, i32, i64, isize);
-
-#[cfg(not(stage0))]
cross_sign_from_int_impl!(u8, i8, i16, i32, i64, i128, isize);
-#[cfg(not(stage0))]
cross_sign_from_int_impl!(u16, i8, i16, i32, i64, i128, isize);
-#[cfg(not(stage0))]
cross_sign_from_int_impl!(u32, i8, i16, i32, i64, i128, isize);
-#[cfg(not(stage0))]
cross_sign_from_int_impl!(u64, i8, i16, i32, i64, i128, isize);
-#[cfg(not(stage0))]
cross_sign_from_int_impl!(u128, i8, i16, i32, i64, i128, isize);
-#[cfg(not(stage0))]
cross_sign_from_int_impl!(usize, i8, i16, i32, i64, i128, isize);
#[doc(hidden)]
}
})*)
}
-doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
-#[cfg(not(stage0))]
-doit! { i128 u128 }
+doit! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, ParseIntError> {
use self::IntErrorKind::*;
impl_from! { u8, u16 }
impl_from! { u8, u32 }
impl_from! { u8, u64 }
-#[cfg(not(stage0))]
impl_from! { u8, u128 }
impl_from! { u8, usize }
impl_from! { u16, u32 }
impl_from! { u16, u64 }
-#[cfg(not(stage0))]
impl_from! { u16, u128 }
impl_from! { u32, u64 }
-#[cfg(not(stage0))]
impl_from! { u32, u128 }
-#[cfg(not(stage0))]
impl_from! { u64, u128 }
// Signed -> Signed
impl_from! { i8, i16 }
impl_from! { i8, i32 }
impl_from! { i8, i64 }
-#[cfg(not(stage0))]
impl_from! { i8, i128 }
impl_from! { i8, isize }
impl_from! { i16, i32 }
impl_from! { i16, i64 }
-#[cfg(not(stage0))]
impl_from! { i16, i128 }
impl_from! { i32, i64 }
-#[cfg(not(stage0))]
impl_from! { i32, i128 }
-#[cfg(not(stage0))]
impl_from! { i64, i128 }
// Unsigned -> Signed
impl_from! { u8, i16 }
impl_from! { u8, i32 }
impl_from! { u8, i64 }
-#[cfg(not(stage0))]
impl_from! { u8, i128 }
impl_from! { u16, i32 }
impl_from! { u16, i64 }
-#[cfg(not(stage0))]
impl_from! { u16, i128 }
impl_from! { u32, i64 }
-#[cfg(not(stage0))]
impl_from! { u32, i128 }
-#[cfg(not(stage0))]
impl_from! { u64, i128 }
// Note: integers can only be represented with full precision in a float if
macro_rules! uint_module {
($T:ident) => (uint_module!($T, #[stable(feature = "rust1", since = "1.0.0")]););
- ($T:ident, $($attr: tt)*) => (
+ ($T:ident, #[$attr:meta]) => (
/// The smallest value that can be represented by this integer type.
- $($attr)*
+ #[$attr]
pub const MIN: $T = $T::min_value();
/// The largest value that can be represented by this integer type.
- $($attr)*
+ #[$attr]
pub const MAX: $T = $T::max_value();
)
}
Wrapping(self.0.wrapping_add(other.0))
}
}
- forward_ref_binop! { impl Add, add for Wrapping<$t>, Wrapping<$t> }
+ forward_ref_binop! { impl Add, add for Wrapping<$t>, Wrapping<$t>,
+ #[stable(feature = "wrapping_ref", since = "1.14.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl AddAssign for Wrapping<$t> {
Wrapping(self.0.wrapping_sub(other.0))
}
}
- forward_ref_binop! { impl Sub, sub for Wrapping<$t>, Wrapping<$t> }
+ forward_ref_binop! { impl Sub, sub for Wrapping<$t>, Wrapping<$t>,
+ #[stable(feature = "wrapping_ref", since = "1.14.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl SubAssign for Wrapping<$t> {
Wrapping(self.0.wrapping_mul(other.0))
}
}
- forward_ref_binop! { impl Mul, mul for Wrapping<$t>, Wrapping<$t> }
+ forward_ref_binop! { impl Mul, mul for Wrapping<$t>, Wrapping<$t>,
+ #[stable(feature = "wrapping_ref", since = "1.14.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl MulAssign for Wrapping<$t> {
Wrapping(self.0.wrapping_div(other.0))
}
}
- forward_ref_binop! { impl Div, div for Wrapping<$t>, Wrapping<$t> }
+ forward_ref_binop! { impl Div, div for Wrapping<$t>, Wrapping<$t>,
+ #[stable(feature = "wrapping_ref", since = "1.14.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl DivAssign for Wrapping<$t> {
Wrapping(self.0.wrapping_rem(other.0))
}
}
- forward_ref_binop! { impl Rem, rem for Wrapping<$t>, Wrapping<$t> }
+ forward_ref_binop! { impl Rem, rem for Wrapping<$t>, Wrapping<$t>,
+ #[stable(feature = "wrapping_ref", since = "1.14.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl RemAssign for Wrapping<$t> {
Wrapping(!self.0)
}
}
- forward_ref_unop! { impl Not, not for Wrapping<$t> }
+ forward_ref_unop! { impl Not, not for Wrapping<$t>,
+ #[stable(feature = "wrapping_ref", since = "1.14.0")] }
#[stable(feature = "rust1", since = "1.0.0")]
impl BitXor for Wrapping<$t> {
Wrapping(self.0 ^ other.0)
}
}
- forward_ref_binop! { impl BitXor, bitxor for Wrapping<$t>, Wrapping<$t> }
+ forward_ref_binop! { impl BitXor, bitxor for Wrapping<$t>, Wrapping<$t>,
+ #[stable(feature = "wrapping_ref", since = "1.14.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl BitXorAssign for Wrapping<$t> {
Wrapping(self.0 | other.0)
}
}
- forward_ref_binop! { impl BitOr, bitor for Wrapping<$t>, Wrapping<$t> }
+ forward_ref_binop! { impl BitOr, bitor for Wrapping<$t>, Wrapping<$t>,
+ #[stable(feature = "wrapping_ref", since = "1.14.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl BitOrAssign for Wrapping<$t> {
Wrapping(self.0 & other.0)
}
}
- forward_ref_binop! { impl BitAnd, bitand for Wrapping<$t>, Wrapping<$t> }
+ forward_ref_binop! { impl BitAnd, bitand for Wrapping<$t>, Wrapping<$t>,
+ #[stable(feature = "wrapping_ref", since = "1.14.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl BitAndAssign for Wrapping<$t> {
Wrapping(0) - self
}
}
- forward_ref_unop! { impl Neg, neg for Wrapping<$t> }
+ forward_ref_unop! { impl Neg, neg for Wrapping<$t>,
+ #[stable(feature = "wrapping_ref", since = "1.14.0")] }
)*)
}
-wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
-#[cfg(not(stage0))]
-wrapping_impl! { u128 i128 }
+wrapping_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
mod shift_max {
#![allow(non_upper_case_globals)]
)*)
}
-add_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
-#[cfg(not(stage0))]
-add_impl! { u128 i128 }
+add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// The `Sub` trait is used to specify the functionality of `-`.
///
)*)
}
-sub_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
-#[cfg(not(stage0))]
-sub_impl! { u128 i128 }
+sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// The `Mul` trait is used to specify the functionality of `*`.
///
)*)
}
-mul_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
-#[cfg(not(stage0))]
-mul_impl! { u128 i128 }
+mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// The `Div` trait is used to specify the functionality of `/`.
///
)*)
}
-div_impl_integer! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
-#[cfg(not(stage0))]
-div_impl_integer! { u128 i128 }
+div_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
macro_rules! div_impl_float {
($($t:ty)*) => ($(
)*)
}
-rem_impl_integer! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
-#[cfg(not(stage0))]
-rem_impl_integer! { u128 i128 }
+rem_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
macro_rules! rem_impl_float {
}
// neg_impl_unsigned! { usize u8 u16 u32 u64 }
-neg_impl_numeric! { isize i8 i16 i32 i64 f32 f64 }
-#[cfg(not(stage0))]
-neg_impl_numeric! { i128 }
+neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 }
/// The `Not` trait is used to specify the functionality of unary `!`.
///
)*)
}
-not_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
-#[cfg(not(stage0))]
-not_impl! { u128 i128 }
+not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// The `BitAnd` trait is used to specify the functionality of `&`.
///
)*)
}
-bitand_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
-#[cfg(not(stage0))]
-bitand_impl! { u128 i128 }
+bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// The `BitOr` trait is used to specify the functionality of `|`.
///
)*)
}
-bitor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
-#[cfg(not(stage0))]
-bitor_impl! { u128 i128 }
+bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// The `BitXor` trait is used to specify the functionality of `^`.
///
)*)
}
-bitxor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
-#[cfg(not(stage0))]
-bitxor_impl! { u128 i128 }
+bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// The `Shl` trait is used to specify the functionality of `<<`.
///
shl_impl! { $t, u16 }
shl_impl! { $t, u32 }
shl_impl! { $t, u64 }
- #[cfg(not(stage0))]
shl_impl! { $t, u128 }
shl_impl! { $t, usize }
shl_impl! { $t, i16 }
shl_impl! { $t, i32 }
shl_impl! { $t, i64 }
- #[cfg(not(stage0))]
shl_impl! { $t, i128 }
shl_impl! { $t, isize }
)*)
}
-shl_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
-#[cfg(not(stage0))]
-shl_impl_all! { u128 i128 }
+shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
/// The `Shr` trait is used to specify the functionality of `>>`.
///
shr_impl! { $t, u16 }
shr_impl! { $t, u32 }
shr_impl! { $t, u64 }
- #[cfg(not(stage0))]
shr_impl! { $t, u128 }
shr_impl! { $t, usize }
shr_impl! { $t, i16 }
shr_impl! { $t, i32 }
shr_impl! { $t, i64 }
- #[cfg(not(stage0))]
shr_impl! { $t, i128 }
shr_impl! { $t, isize }
)*)
}
-shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
-#[cfg(not(stage0))]
-shr_impl_all! { u128 i128 }
+shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
/// The `AddAssign` trait is used to specify the functionality of `+=`.
///
)+)
}
-add_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
-#[cfg(not(stage0))]
-add_assign_impl! { u128 i128 }
+add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// The `SubAssign` trait is used to specify the functionality of `-=`.
///
)+)
}
-sub_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
-#[cfg(not(stage0))]
-sub_assign_impl! { u128 i128 }
+sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// The `MulAssign` trait is used to specify the functionality of `*=`.
///
)+)
}
-mul_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
-#[cfg(not(stage0))]
-mul_assign_impl! { u128 i128 }
+mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// The `DivAssign` trait is used to specify the functionality of `/=`.
///
)+)
}
-div_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
-#[cfg(not(stage0))]
-div_assign_impl! { u128 i128 }
+div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// The `RemAssign` trait is used to specify the functionality of `%=`.
///
)+)
}
-rem_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
-#[cfg(not(stage0))]
-rem_assign_impl! { u128 i128 }
+rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// The `BitAndAssign` trait is used to specify the functionality of `&=`.
///
)+)
}
-bitand_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
-#[cfg(not(stage0))]
-bitand_assign_impl! { u128 i128 }
+bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// The `BitOrAssign` trait is used to specify the functionality of `|=`.
///
)+)
}
-bitor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
-#[cfg(not(stage0))]
-bitor_assign_impl! { u128 i128 }
+bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// The `BitXorAssign` trait is used to specify the functionality of `^=`.
///
)+)
}
-bitxor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
-#[cfg(not(stage0))]
-bitxor_assign_impl! { u128 i128 }
+bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// The `ShlAssign` trait is used to specify the functionality of `<<=`.
///
shl_assign_impl! { $t, u16 }
shl_assign_impl! { $t, u32 }
shl_assign_impl! { $t, u64 }
- #[cfg(not(stage0))]
shl_assign_impl! { $t, u128 }
shl_assign_impl! { $t, usize }
shl_assign_impl! { $t, i16 }
shl_assign_impl! { $t, i32 }
shl_assign_impl! { $t, i64 }
- #[cfg(not(stage0))]
shl_assign_impl! { $t, i128 }
shl_assign_impl! { $t, isize }
)*)
}
-shl_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
-#[cfg(not(stage0))]
-shl_assign_impl_all! { u128 i128 }
+shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
/// The `ShrAssign` trait is used to specify the functionality of `>>=`.
///
shr_assign_impl! { $t, u16 }
shr_assign_impl! { $t, u32 }
shr_assign_impl! { $t, u64 }
- #[cfg(not(stage0))]
shr_assign_impl! { $t, u128 }
shr_assign_impl! { $t, usize }
shr_assign_impl! { $t, i16 }
shr_assign_impl! { $t, i32 }
shr_assign_impl! { $t, i64 }
- #[cfg(not(stage0))]
shr_assign_impl! { $t, i128 }
shr_assign_impl! { $t, isize }
)*)
}
-shr_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
-#[cfg(not(stage0))]
-shr_assign_impl_all! { u128 i128 }
+shr_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
/// The `Index` trait is used to specify the functionality of indexing operations
/// like `container[index]` when used in an immutable context.
}
}
+ /////////////////////////////////////////////////////////////////////////
+ // Entry-like operations to insert if None and return a reference
+ /////////////////////////////////////////////////////////////////////////
+
+ /// Inserts `v` into the option if it is `None`, then
+ /// returns a mutable reference to the contained value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(option_entry)]
+ ///
+ /// let mut x = None;
+ ///
+ /// {
+ /// let y: &mut u32 = x.get_or_insert(5);
+ /// assert_eq!(y, &5);
+ ///
+ /// *y = 7;
+ /// }
+ ///
+ /// assert_eq!(x, Some(7));
+ /// ```
+ #[inline]
+ #[unstable(feature = "option_entry", issue = "39288")]
+ pub fn get_or_insert(&mut self, v: T) -> &mut T {
+ match *self {
+ None => *self = Some(v),
+ _ => (),
+ }
+
+ match *self {
+ Some(ref mut v) => v,
+ _ => unreachable!(),
+ }
+ }
+
+ /// Inserts a value computed from `f` into the option if it is `None`, then
+ /// returns a mutable reference to the contained value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(option_entry)]
+ ///
+ /// let mut x = None;
+ ///
+ /// {
+ /// let y: &mut u32 = x.get_or_insert_with(|| 5);
+ /// assert_eq!(y, &5);
+ ///
+ /// *y = 7;
+ /// }
+ ///
+ /// assert_eq!(x, Some(7));
+ /// ```
+ #[inline]
+ #[unstable(feature = "option_entry", issue = "39288")]
+ pub fn get_or_insert_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
+ match *self {
+ None => *self = Some(f()),
+ _ => (),
+ }
+
+ match *self {
+ Some(ref mut v) => v,
+ _ => unreachable!(),
+ }
+ }
+
/////////////////////////////////////////////////////////////////////////
// Misc
/////////////////////////////////////////////////////////////////////////
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output;
}
-#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
+#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
impl<T> SliceIndex<T> for usize {
type Output = T;
}
}
-#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
+#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
impl<T> SliceIndex<T> for ops::Range<usize> {
type Output = [T];
}
}
-#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
+#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
impl<T> SliceIndex<T> for ops::RangeTo<usize> {
type Output = [T];
}
}
-#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
+#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
impl<T> SliceIndex<T> for ops::RangeFrom<usize> {
type Output = [T];
}
}
-#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
+#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
impl<T> SliceIndex<T> for ops::RangeFull {
type Output = [T];
}
-#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
+#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
impl<T> SliceIndex<T> for ops::RangeInclusive<usize> {
type Output = [T];
}
}
-#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
+#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
impl<T> SliceIndex<T> for ops::RangeToInclusive<usize> {
type Output = [T];
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
use core::any::*;
-use test::Bencher;
-use test;
#[derive(PartialEq, Debug)]
struct Test;
fn is_any<T: Any + ?Sized>() {}
is_any::<[i32]>();
}
-
-#[bench]
-fn bench_downcast_ref(b: &mut Bencher) {
- b.iter(|| {
- let mut x = 0;
- let mut y = &mut x as &mut Any;
- test::black_box(&mut y);
- test::black_box(y.downcast_ref::<isize>() == Some(&0));
- });
-}
assert_eq!(0, cell.get());
}
+#[test]
+fn cell_set() {
+ let cell = Cell::new(10);
+ cell.set(20);
+ assert_eq!(20, cell.get());
+
+ let cell = Cell::new("Hello".to_owned());
+ cell.set("World".to_owned());
+ assert_eq!("World".to_owned(), cell.into_inner());
+}
+
+#[test]
+fn cell_replace() {
+ let cell = Cell::new(10);
+ assert_eq!(10, cell.replace(20));
+ assert_eq!(20, cell.get());
+
+ let cell = Cell::new("Hello".to_owned());
+ assert_eq!("Hello".to_owned(), cell.replace("World".to_owned()));
+ assert_eq!("World".to_owned(), cell.into_inner());
+}
+
+#[test]
+fn cell_into_inner() {
+ let cell = Cell::new(10);
+ assert_eq!(10, cell.into_inner());
+
+ let cell = Cell::new("Hello world".to_owned());
+ assert_eq!("Hello world".to_owned(), cell.into_inner());
+}
+
#[test]
fn refcell_default() {
let cell: RefCell<u64> = Default::default();
assert_eq!(format!("{:p}", s), format!("{:p}", s.as_ptr()));
assert_eq!(format!("{:p}", b), format!("{:p}", b.as_ptr()));
}
+
+#[test]
+fn test_estimated_capacity() {
+ assert_eq!(format_args!("").estimated_capacity(), 0);
+ assert_eq!(format_args!("{}", "").estimated_capacity(), 0);
+ assert_eq!(format_args!("Hello").estimated_capacity(), 5);
+ assert_eq!(format_args!("Hello, {}!", "").estimated_capacity(), 16);
+ assert_eq!(format_args!("{}, hello!", "World").estimated_capacity(), 0);
+ assert_eq!(format_args!("{}. 16-bytes piece", "World").estimated_capacity(), 32);
+}
assert_eq!(hash(& s), 97 + 0xFF);
let cs: &[u8] = &[1, 2, 3];
assert_eq!(hash(& cs), 9);
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let cs: Box<[u8]> = Box::new([1, 2, 3]);
assert_eq!(hash(& cs), 9);
#![allow(deprecated)]
-use test::{Bencher, black_box};
-
use core::hash::{Hash, Hasher};
use core::hash::{SipHasher, SipHasher13, SipHasher24};
use core::{slice, mem};
hash_with(SipHasher::new(), x)
}
-fn hash_bytes<H: Hasher>(mut s: H, x: &[u8]) -> u64 {
- Hasher::write(&mut s, x);
- s.finish()
-}
-
#[test]
#[allow(unused_must_use)]
fn test_siphash_1_3() {
h2.write(&[0xFFu8, 0x01u8]);
assert_eq!(h1.finish(), h2.finish());
}
-
-#[bench]
-fn bench_str_under_8_bytes(b: &mut Bencher) {
- let s = "foo";
- b.iter(|| {
- assert_eq!(hash(&s), 16262950014981195938);
- })
-}
-
-#[bench]
-fn bench_str_of_8_bytes(b: &mut Bencher) {
- let s = "foobar78";
- b.iter(|| {
- assert_eq!(hash(&s), 4898293253460910787);
- })
-}
-
-#[bench]
-fn bench_str_over_8_bytes(b: &mut Bencher) {
- let s = "foobarbaz0";
- b.iter(|| {
- assert_eq!(hash(&s), 10581415515220175264);
- })
-}
-
-#[bench]
-fn bench_long_str(b: &mut Bencher) {
- let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \
-incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \
-exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute \
-irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \
-pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \
-officia deserunt mollit anim id est laborum.";
- b.iter(|| {
- assert_eq!(hash(&s), 17717065544121360093);
- })
-}
-
-#[bench]
-fn bench_u32(b: &mut Bencher) {
- let u = 162629500u32;
- let u = black_box(u);
- b.iter(|| {
- hash(&u)
- });
- b.bytes = 8;
-}
-
-#[bench]
-fn bench_u32_keyed(b: &mut Bencher) {
- let u = 162629500u32;
- let u = black_box(u);
- let k1 = black_box(0x1);
- let k2 = black_box(0x2);
- b.iter(|| {
- hash_with(SipHasher::new_with_keys(k1, k2), &u)
- });
- b.bytes = 8;
-}
-
-#[bench]
-fn bench_u64(b: &mut Bencher) {
- let u = 16262950014981195938u64;
- let u = black_box(u);
- b.iter(|| {
- hash(&u)
- });
- b.bytes = 8;
-}
-
-#[bench]
-fn bench_bytes_4(b: &mut Bencher) {
- let data = black_box([b' '; 4]);
- b.iter(|| {
- hash_bytes(SipHasher::default(), &data)
- });
- b.bytes = 4;
-}
-
-#[bench]
-fn bench_bytes_7(b: &mut Bencher) {
- let data = black_box([b' '; 7]);
- b.iter(|| {
- hash_bytes(SipHasher::default(), &data)
- });
- b.bytes = 7;
-}
-
-#[bench]
-fn bench_bytes_8(b: &mut Bencher) {
- let data = black_box([b' '; 8]);
- b.iter(|| {
- hash_bytes(SipHasher::default(), &data)
- });
- b.bytes = 8;
-}
-
-#[bench]
-fn bench_bytes_a_16(b: &mut Bencher) {
- let data = black_box([b' '; 16]);
- b.iter(|| {
- hash_bytes(SipHasher::default(), &data)
- });
- b.bytes = 16;
-}
-
-#[bench]
-fn bench_bytes_b_32(b: &mut Bencher) {
- let data = black_box([b' '; 32]);
- b.iter(|| {
- hash_bytes(SipHasher::default(), &data)
- });
- b.bytes = 32;
-}
-
-#[bench]
-fn bench_bytes_c_128(b: &mut Bencher) {
- let data = black_box([b' '; 128]);
- b.iter(|| {
- hash_bytes(SipHasher::default(), &data)
- });
- b.bytes = 128;
-}
use core::{i8, i16, isize};
use core::usize;
-use test::Bencher;
-use test::black_box;
-
#[test]
fn test_lt() {
let empty: [isize; 0] = [];
assert_eq!(xs.iter().count(), 6);
}
+#[test]
+fn test_iterator_filter_count() {
+ let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8];
+ assert_eq!(xs.iter().filter(|&&x| x % 2 == 0).count(), 5);
+}
+
#[test]
fn test_iterator_peekable() {
let xs = vec![0, 1, 2, 3, 4, 5];
#[test]
fn test_all() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]);
assert!(v.iter().all(|&x| x < 10));
assert!(!v.iter().all(|&x| x % 2 == 0));
#[test]
fn test_any() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]);
assert!(v.iter().any(|&x| x < 10));
assert!(v.iter().any(|&x| x % 2 == 0));
assert_eq!(&[2, 3, 1, 2, 0], &result[..]);
}
-#[bench]
-fn bench_rposition(b: &mut Bencher) {
- let it: Vec<usize> = (0..300).collect();
- b.iter(|| {
- it.iter().rposition(|&x| x <= 150);
- });
-}
-
-#[bench]
-fn bench_skip_while(b: &mut Bencher) {
- b.iter(|| {
- let it = 0..100;
- let mut sum = 0;
- it.skip_while(|&x| { sum += x; sum < 4000 }).all(|_| true);
- });
-}
-
-#[bench]
-fn bench_multiple_take(b: &mut Bencher) {
- let mut it = (0..42).cycle();
- b.iter(|| {
- let n = it.next().unwrap();
- for _ in 0..n {
- it.clone().take(it.next().unwrap()).all(|_| true);
- }
- });
-}
-
-fn scatter(x: i32) -> i32 { (x * 31) % 127 }
-
-#[bench]
-fn bench_max_by_key(b: &mut Bencher) {
- b.iter(|| {
- let it = 0..100;
- it.max_by_key(|&x| scatter(x))
- })
-}
-
-// http://www.reddit.com/r/rust/comments/31syce/using_iterators_to_find_the_index_of_the_min_or/
-#[bench]
-fn bench_max_by_key2(b: &mut Bencher) {
- fn max_index_iter(array: &[i32]) -> usize {
- array.iter().enumerate().max_by_key(|&(_, item)| item).unwrap().0
- }
-
- let mut data = vec![0; 1638];
- data[514] = 9999;
-
- b.iter(|| max_index_iter(&data));
-}
-
-#[bench]
-fn bench_max(b: &mut Bencher) {
- b.iter(|| {
- let it = 0..100;
- it.map(scatter).max()
- })
-}
-
-pub fn copy_zip(xs: &[u8], ys: &mut [u8]) {
- for (a, b) in ys.iter_mut().zip(xs) {
- *a = *b;
- }
-}
-
-pub fn add_zip(xs: &[f32], ys: &mut [f32]) {
- for (a, b) in ys.iter_mut().zip(xs) {
- *a += *b;
- }
-}
-
-#[bench]
-fn bench_zip_copy(b: &mut Bencher) {
- let source = vec![0u8; 16 * 1024];
- let mut dst = black_box(vec![0u8; 16 * 1024]);
- b.iter(|| {
- copy_zip(&source, &mut dst)
- })
-}
-
-#[bench]
-fn bench_zip_add(b: &mut Bencher) {
- let source = vec![1.; 16 * 1024];
- let mut dst = vec![0.; 16 * 1024];
- b.iter(|| {
- add_zip(&source, &mut dst)
- });
-}
#![feature(unique)]
#![feature(ordering_chaining)]
#![feature(ptr_unaligned)]
+#![feature(move_cell)]
+#![feature(fmt_internals)]
extern crate core;
extern crate test;
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
use core::mem::*;
-use test::Bencher;
#[test]
fn size_of_basic() {
}
}
-// FIXME #13642 (these benchmarks should be in another place)
-/// Completely miscellaneous language-construct benchmarks.
-// Static/dynamic method dispatch
-
-struct Struct {
- field: isize
-}
-
-trait Trait {
- fn method(&self) -> isize;
-}
-
-impl Trait for Struct {
- fn method(&self) -> isize {
- self.field
- }
-}
-
-#[bench]
-fn trait_vtable_method_call(b: &mut Bencher) {
- let s = Struct { field: 10 };
- let t = &s as &Trait;
- b.iter(|| {
- t.method()
- });
-}
-
-#[bench]
-fn trait_static_method_call(b: &mut Bencher) {
- let s = Struct { field: 10 };
- b.iter(|| {
- s.method()
- });
-}
-
-// Overhead of various match forms
-
-#[bench]
-fn match_option_some(b: &mut Bencher) {
- let x = Some(10);
- b.iter(|| {
- match x {
- Some(y) => y,
- None => 11
- }
- });
-}
-
-#[bench]
-fn match_vec_pattern(b: &mut Bencher) {
- let x = [1,2,3,4,5,6];
- b.iter(|| {
- match x {
- [1,2,3,..] => 10,
- _ => 11,
- }
- });
-}
#![allow(overflowing_literals)]
use std::{i64, f32, f64};
-use test;
mod parse;
mod rawfp;
// It makes no sense to enshrine that in a test, the important part is that it doesn't panic.
let _ = s.parse::<f64>();
}
-
-#[bench]
-fn bench_0(b: &mut test::Bencher) {
- b.iter(|| "0.0".parse::<f64>());
-}
-
-#[bench]
-fn bench_42(b: &mut test::Bencher) {
- b.iter(|| "42".parse::<f64>());
-}
-
-#[bench]
-fn bench_huge_int(b: &mut test::Bencher) {
- // 2^128 - 1
- b.iter(|| "170141183460469231731687303715884105727".parse::<f64>());
-}
-
-#[bench]
-fn bench_short_decimal(b: &mut test::Bencher) {
- b.iter(|| "1234.5678".parse::<f64>());
-}
-
-#[bench]
-fn bench_pi_long(b: &mut test::Bencher) {
- b.iter(|| "3.14159265358979323846264338327950288".parse::<f64>());
-}
-
-#[bench]
-fn bench_pi_short(b: &mut test::Bencher) {
- b.iter(|| "3.141592653589793".parse::<f64>())
-}
-
-#[bench]
-fn bench_1e150(b: &mut test::Bencher) {
- b.iter(|| "1e150".parse::<f64>());
-}
-
-#[bench]
-fn bench_long_decimal_and_exp(b: &mut test::Bencher) {
- b.iter(|| "727501488517303786137132964064381141071e-123".parse::<f64>());
-}
-
-#[bench]
-fn bench_min_subnormal(b: &mut test::Bencher) {
- b.iter(|| "5e-324".parse::<f64>());
-}
-
-#[bench]
-fn bench_min_normal(b: &mut test::Bencher) {
- b.iter(|| "2.2250738585072014e-308".parse::<f64>());
-}
-
-#[bench]
-fn bench_max(b: &mut test::Bencher) {
- b.iter(|| "1.7976931348623157e308".parse::<f64>());
-}
// except according to those terms.
use std::prelude::v1::*;
-use std::{i16, f64};
use super::super::*;
use core::num::bignum::Big32x40 as Big;
use core::num::flt2dec::strategy::dragon::*;
f32_exact_sanity_test(format_exact);
}
-#[bench]
-fn bench_small_shortest(b: &mut Bencher) {
- let decoded = decode_finite(3.141592f64);
- let mut buf = [0; MAX_SIG_DIGITS];
- b.iter(|| format_shortest(&decoded, &mut buf));
-}
-
-#[bench]
-fn bench_big_shortest(b: &mut Bencher) {
- let decoded = decode_finite(f64::MAX);
- let mut buf = [0; MAX_SIG_DIGITS];
- b.iter(|| format_shortest(&decoded, &mut buf));
-}
-
-#[bench]
-fn bench_small_exact_3(b: &mut Bencher) {
- let decoded = decode_finite(3.141592f64);
- let mut buf = [0; 3];
- b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
-}
-
-#[bench]
-fn bench_big_exact_3(b: &mut Bencher) {
- let decoded = decode_finite(f64::MAX);
- let mut buf = [0; 3];
- b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
-}
-
-#[bench]
-fn bench_small_exact_12(b: &mut Bencher) {
- let decoded = decode_finite(3.141592f64);
- let mut buf = [0; 12];
- b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
-}
-
-#[bench]
-fn bench_big_exact_12(b: &mut Bencher) {
- let decoded = decode_finite(f64::MAX);
- let mut buf = [0; 12];
- b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
-}
-
-#[bench]
-fn bench_small_exact_inf(b: &mut Bencher) {
- let decoded = decode_finite(3.141592f64);
- let mut buf = [0; 1024];
- b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
-}
-
-#[bench]
-fn bench_big_exact_inf(b: &mut Bencher) {
- let decoded = decode_finite(f64::MAX);
- let mut buf = [0; 1024];
- b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
-}
-
#[test]
fn test_to_shortest_str() {
to_shortest_str_test(format_shortest);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::{i16, f64};
+use std::i16;
use super::super::*;
use core::num::flt2dec::strategy::grisu::*;
}
}
-#[bench]
-fn bench_small_shortest(b: &mut Bencher) {
- let decoded = decode_finite(3.141592f64);
- let mut buf = [0; MAX_SIG_DIGITS];
- b.iter(|| format_shortest(&decoded, &mut buf));
-}
-
-#[bench]
-fn bench_big_shortest(b: &mut Bencher) {
- let decoded = decode_finite(f64::MAX);
- let mut buf = [0; MAX_SIG_DIGITS];
- b.iter(|| format_shortest(&decoded, &mut buf));
-}
-
-#[bench]
-fn bench_small_exact_3(b: &mut Bencher) {
- let decoded = decode_finite(3.141592f64);
- let mut buf = [0; 3];
- b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
-}
-
-#[bench]
-fn bench_big_exact_3(b: &mut Bencher) {
- let decoded = decode_finite(f64::MAX);
- let mut buf = [0; 3];
- b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
-}
-
-#[bench]
-fn bench_small_exact_12(b: &mut Bencher) {
- let decoded = decode_finite(3.141592f64);
- let mut buf = [0; 12];
- b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
-}
-
-#[bench]
-fn bench_big_exact_12(b: &mut Bencher) {
- let decoded = decode_finite(f64::MAX);
- let mut buf = [0; 12];
- b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
-}
-
-#[bench]
-fn bench_small_exact_inf(b: &mut Bencher) {
- let decoded = decode_finite(3.141592f64);
- let mut buf = [0; 1024];
- b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
-}
-
-#[bench]
-fn bench_big_exact_inf(b: &mut Bencher) {
- let decoded = decode_finite(f64::MAX);
- let mut buf = [0; 1024];
- b.iter(|| format_exact(&decoded, &mut buf, i16::MIN));
-}
-
#[test]
fn test_to_shortest_str() {
to_shortest_str_test(format_shortest);
test_impl_try_from_same_sign_err! { test_try_i64i8, i64, i8 }
test_impl_try_from_same_sign_err! { test_try_i64i16, i64, i16 }
test_impl_try_from_same_sign_err! { test_try_i64i32, i64, i32 }
+
+macro_rules! test_impl_try_from_signed_to_unsigned_err {
+ ($fn_name:ident, $source:ty, $target:ty) => {
+ #[test]
+ fn $fn_name() {
+ let max = <$source>::max_value();
+ let min = <$source>::min_value();
+ let zero: $source = 0;
+ let t_max = <$target>::max_value();
+ let t_min = <$target>::min_value();
+ assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
+ assert!(<$target as TryFrom<$source>>::try_from(min).is_err());
+ assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+ zero as $target);
+ assert_eq!(<$target as TryFrom<$source>>::try_from(t_max as $source)
+ .unwrap(),
+ t_max as $target);
+ assert_eq!(<$target as TryFrom<$source>>::try_from(t_min as $source)
+ .unwrap(),
+ t_min as $target);
+ }
+ }
+}
+
+test_impl_try_from_signed_to_unsigned_err! { test_try_i16u8, i16, u8 }
+
+test_impl_try_from_signed_to_unsigned_err! { test_try_i32u8, i32, u8 }
+test_impl_try_from_signed_to_unsigned_err! { test_try_i32u16, i32, u16 }
+
+test_impl_try_from_signed_to_unsigned_err! { test_try_i64u8, i64, u8 }
+test_impl_try_from_signed_to_unsigned_err! { test_try_i64u16, i64, u16 }
+test_impl_try_from_signed_to_unsigned_err! { test_try_i64u32, i64, u32 }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use test::Bencher;
use core::ops::{Range, RangeFull, RangeFrom, RangeTo};
-// Overhead of dtors
-
-struct HasDtor {
- _x: isize
-}
-
-impl Drop for HasDtor {
- fn drop(&mut self) {
- }
-}
-
-#[bench]
-fn alloc_obj_with_dtor(b: &mut Bencher) {
- b.iter(|| {
- HasDtor { _x : 10 };
- })
-}
-
// Test the Range structs without the syntactic sugar.
#[test]
-Subproject commit 7d57bdcdbb56540f37afe5a934ce12d33a6ca7fc
+Subproject commit cb7f66732175e6171587ed69656b7aae7dd2e6ec
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
rustc_llvm = { path = "../librustc_llvm" }
-rustc_i128 = { path = "../librustc_i128" }
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
AssociatedItemDefIds(D),
InherentImpls(D),
TypeckTables(D),
+ UsedTraitImports(D),
// The set of impls for a given trait. Ultimately, it would be
// nice to get more fine-grained here (e.g., to include a
AssociatedItemDefIds,
InherentImpls,
TypeckTables,
+ UsedTraitImports,
TraitImpls,
ReprHints,
}
AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
InherentImpls(ref d) => op(d).map(InherentImpls),
TypeckTables(ref d) => op(d).map(TypeckTables),
+ UsedTraitImports(ref d) => op(d).map(UsedTraitImports),
TraitImpls(ref d) => op(d).map(TraitImpls),
TraitItems(ref d) => op(d).map(TraitItems),
ReprHints(ref d) => op(d).map(ReprHints),
self.map.get(k)
}
- pub fn get_mut(&mut self, k: &M::Key) -> Option<&mut M::Value> {
- self.read(k);
- self.write(k);
- self.map.get_mut(k)
- }
-
- pub fn insert(&mut self, k: M::Key, v: M::Value) -> Option<M::Value> {
+ pub fn insert(&mut self, k: M::Key, v: M::Value) {
self.write(&k);
- self.map.insert(k, v)
+ let old_value = self.map.insert(k, v);
+ assert!(old_value.is_none());
}
pub fn contains_key(&self, k: &M::Key) -> bool {
/// Append `elem` to the vector stored for `k`, creating a new vector if needed.
/// This is considered a write to `k`.
+ ///
+ /// NOTE: Caution is required when using this method. You should
+ /// be sure that nobody is **reading from the vector** while you
+ /// are writing to it. Eventually, it'd be nice to remove this.
pub fn push<E: Clone>(&mut self, k: M::Key, elem: E)
where M: DepTrackingMapConfig<Value=Vec<E>>
{
You can build a free-standing crate by adding `#![no_std]` to the crate
attributes:
-```
+```ignore
#![no_std]
```
pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
visitor.visit_id(expression.id);
+ walk_list!(visitor, visit_attribute, expression.attrs.iter());
match expression.node {
ExprBox(ref subexpression) => {
visitor.visit_expr(subexpression)
use hir::map as hir_map;
use hir;
-use lint;
use hir::def_id::DefId;
use infer;
use middle::region;
use traits::{ObligationCause, ObligationCauseCode};
use ty::{self, TyCtxt, TypeFoldable};
-use ty::{Region, ReFree};
+use ty::{Region, ReFree, Issue32330};
use ty::error::TypeError;
use std::fmt;
self.tcx.note_and_explain_type_err(diag, terr, span);
}
+ pub fn note_issue_32330(&self,
+ diag: &mut DiagnosticBuilder<'tcx>,
+ terr: &TypeError<'tcx>)
+ {
+ debug!("note_issue_32330: terr={:?}", terr);
+ match *terr {
+ TypeError::RegionsInsufficientlyPolymorphic(_, &Region::ReVar(vid)) |
+ TypeError::RegionsOverlyPolymorphic(_, &Region::ReVar(vid)) => {
+ match self.region_vars.var_origin(vid) {
+ RegionVariableOrigin::EarlyBoundRegion(_, _, Some(Issue32330 {
+ fn_def_id,
+ region_name
+ })) => {
+ diag.note(
+ &format!("lifetime parameter `{0}` declared on fn `{1}` \
+ appears only in the return type, \
+ but here is required to be higher-ranked, \
+ which means that `{0}` must appear in both \
+ argument and return types",
+ region_name,
+ self.tcx.item_path_str(fn_def_id)));
+ diag.note(
+ &format!("this error is the result of a recent bug fix; \
+ for more information, see issue #33685 \
+ <https://github.com/rust-lang/rust/issues/33685>"));
+ }
+ _ => { }
+ }
+ }
+ _ => { }
+ }
+ }
+
pub fn report_and_explain_type_error(&self,
trace: TypeTrace<'tcx>,
terr: &TypeError<'tcx>)
}
};
self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr);
+ self.note_issue_32330(&mut diag, terr);
diag
}
err.emit();
}
}
-
- pub fn issue_32330_warnings(&self, span: Span, issue32330s: &[ty::Issue32330]) {
- for issue32330 in issue32330s {
- match *issue32330 {
- ty::Issue32330::WontChange => { }
- ty::Issue32330::WillChange { fn_def_id, region_name } => {
- self.tcx.sess.add_lint(
- lint::builtin::HR_LIFETIME_IN_ASSOC_TYPE,
- ast::CRATE_NODE_ID,
- span,
- format!("lifetime parameter `{0}` declared on fn `{1}` \
- appears only in the return type, \
- but here is required to be higher-ranked, \
- which means that `{0}` must appear in both \
- argument and return types",
- region_name,
- self.tcx.item_path_str(fn_def_id)));
- }
- }
- }
- }
}
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
format!(" for lifetime parameter {}in trait containing associated type `{}`",
br_string(br), type_name)
}
- infer::EarlyBoundRegion(_, name) => {
+ infer::EarlyBoundRegion(_, name, _) => {
format!(" for lifetime parameter `{}`",
name)
}
/// hold. See `README.md` for more details.
pub fn leak_check(&self,
overly_polymorphic: bool,
- span: Span,
+ _span: Span,
skol_map: &SkolemizationMap<'tcx>,
snapshot: &CombinedSnapshot)
-> RelateResult<'tcx, ()>
debug!("leak_check: skol_map={:?}",
skol_map);
- // ## Issue #32330 warnings
- //
- // When Issue #32330 is fixed, a certain number of late-bound
- // regions (LBR) will become early-bound. We wish to issue
- // warnings when the result of `leak_check` relies on such LBR, as
- // that means that compilation will likely start to fail.
- //
- // Recall that when we do a "HR subtype" check, we replace all
- // late-bound regions (LBR) in the subtype with fresh variables,
- // and skolemize the late-bound regions in the supertype. If those
- // skolemized regions from the supertype wind up being
- // super-regions (directly or indirectly) of either
- //
- // - another skolemized region; or,
- // - some region that pre-exists the HR subtype check
- // - e.g., a region variable that is not one of those created
- // to represent bound regions in the subtype
- //
- // then leak-check (and hence the subtype check) fails.
- //
- // What will change when we fix #32330 is that some of the LBR in the
- // subtype may become early-bound. In that case, they would no longer be in
- // the "permitted set" of variables that can be related to a skolemized
- // type.
- //
- // So the foundation for this warning is to collect variables that we found
- // to be related to a skolemized type. For each of them, we have a
- // `BoundRegion` which carries a `Issue32330` flag. We check whether any of
- // those flags indicate that this variable was created from a lifetime
- // that will change from late- to early-bound. If so, we issue a warning
- // indicating that the results of compilation may change.
- //
- // This is imperfect, since there are other kinds of code that will not
- // compile once #32330 is fixed. However, it fixes the errors observed in
- // practice on crater runs.
- let mut warnings = vec![];
-
let new_vars = self.region_vars_confined_to_snapshot(snapshot);
for (&skol_br, &skol) in skol_map {
// The inputs to a skolemized variable can only
match *tainted_region {
ty::ReVar(vid) => {
if new_vars.contains(&vid) {
- warnings.extend(
- match self.region_vars.var_origin(vid) {
- LateBoundRegion(_,
- ty::BrNamed(.., wc),
- _) => Some(wc),
- _ => None,
- });
continue;
}
}
}
}
- self.issue_32330_warnings(span, &warnings);
-
Ok(())
}
Coercion(Span),
// Region variables created as the values for early-bound regions
- EarlyBoundRegion(Span, ast::Name),
+ EarlyBoundRegion(Span, ast::Name, Option<ty::Issue32330>),
// Region variables created for bound regions
// in a function or method that is called
span: Span,
def: &ty::RegionParameterDef)
-> &'tcx ty::Region {
- self.next_region_var(EarlyBoundRegion(span, def.name))
+ self.next_region_var(EarlyBoundRegion(span, def.name, def.issue_32330))
}
/// Create a type inference variable for the given
AddrOfRegion(a) => a,
Autoref(a) => a,
Coercion(a) => a,
- EarlyBoundRegion(a, _) => a,
+ EarlyBoundRegion(a, ..) => a,
LateBoundRegion(a, ..) => a,
BoundRegionInCoherence(_) => syntax_pos::DUMMY_SP,
UpvarRegion(_, a) => a
#![feature(const_fn)]
#![feature(core_intrinsics)]
#![feature(field_init_shorthand)]
+#![feature(i128_type)]
#![feature(libc)]
#![feature(loop_break_value)]
#![feature(nonzero)]
extern crate serialize as rustc_serialize; // used by deriving
-// SNAP:
-extern crate rustc_i128;
-
#[macro_use]
mod macros;
pub mod common;
pub mod ppaux;
pub mod nodemap;
- pub mod num;
pub mod fs;
}
"lifetimes or labels named `'_` were erroneously allowed"
}
+declare_lint! {
+ pub RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
+ Warn,
+ "attempt to resolve a trait on an expression whose type cannot be inferred but which \
+ currently defaults to ()"
+}
+
declare_lint! {
pub SAFE_EXTERN_STATICS,
Warn,
"detects names that resolve to ambiguous glob imports with RFC 1560"
}
+declare_lint! {
+ pub LEGACY_CONSTRUCTOR_VISIBILITY,
+ Deny,
+ "detects use of struct constructors that would be invisible with new visibility rules"
+}
+
declare_lint! {
pub DEPRECATED,
Warn,
SUPER_OR_SELF_IN_GLOBAL_PATH,
HR_LIFETIME_IN_ASSOC_TYPE,
LIFETIME_UNDERSCORE,
+ RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
SAFE_EXTERN_STATICS,
PATTERNS_IN_FNS_WITHOUT_BODY,
EXTRA_REQUIREMENT_IN_IMPL,
LEGACY_DIRECTORY_OWNERSHIP,
LEGACY_IMPORTS,
+ LEGACY_CONSTRUCTOR_VISIBILITY,
DEPRECATED
)
}
use lint::{EarlyLintPassObject, LateLintPassObject};
use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid};
use lint::builtin;
+use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
use util::nodemap::FxHashMap;
use std::cmp;
use std::default::Default as StdDefault;
use std::mem;
use std::fmt;
+use std::ops::Deref;
use syntax::attr;
use syntax::ast;
+use syntax::symbol::Symbol;
use syntax_pos::{MultiSpan, Span};
use errors::{self, Diagnostic, DiagnosticBuilder};
use hir;
/// When you call `add_lint` on the session, you wind up storing one
/// of these, which records a "potential lint" at a particular point.
-#[derive(PartialEq)]
+#[derive(PartialEq, RustcEncodable, RustcDecodable)]
pub struct EarlyLint {
/// what lint is this? (e.g., `dead_code`)
pub id: LintId,
check_lint_name_cmdline(sess, self,
&lint_name[..], level);
+ let lint_flag_val = Symbol::intern(&lint_name);
match self.find_lint(&lint_name[..], sess, None) {
- Ok(lint_id) => self.set_level(lint_id, (level, CommandLine)),
+ Ok(lint_id) => self.set_level(lint_id, (level, CommandLine(lint_flag_val))),
Err(FindLintError::Removed) => { }
Err(_) => {
match self.lint_groups.iter().map(|(&x, pair)| (x, pair.0.clone()))
Some(v) => {
v.iter()
.map(|lint_id: &LintId|
- self.set_level(*lint_id, (level, CommandLine)))
+ self.set_level(*lint_id, (level, CommandLine(lint_flag_val))))
.collect::<Vec<()>>();
}
None => {
-> DiagnosticBuilder<'a>
where S: Into<MultiSpan>
{
- let (mut level, source) = lvlsrc;
+ let (level, source) = lvlsrc;
if level == Allow {
return sess.diagnostic().struct_dummy();
}
let name = lint.name_lower();
let mut def = None;
- let msg = match source {
- Default => {
- format!("{}, #[{}({})] on by default", msg,
- level.as_str(), name)
- },
- CommandLine => {
- format!("{} [-{} {}]", msg,
- match level {
- Warn => 'W', Deny => 'D', Forbid => 'F',
- Allow => bug!()
- }, name.replace("_", "-"))
- },
- Node(src) => {
- def = Some(src);
- msg.to_string()
- }
- };
- // For purposes of printing, we can treat forbid as deny.
- if level == Forbid { level = Deny; }
+ // Except for possible note details, forbid behaves like deny.
+ let effective_level = if level == Forbid { Deny } else { level };
- let mut err = match (level, span) {
+ let mut err = match (effective_level, span) {
(Warn, Some(sp)) => sess.struct_span_warn(sp, &msg[..]),
(Warn, None) => sess.struct_warn(&msg[..]),
(Deny, Some(sp)) => sess.struct_span_err(sp, &msg[..]),
_ => bug!("impossible level in raw_emit_lint"),
};
+ match source {
+ Default => {
+ err.note(&format!("#[{}({})] on by default", level.as_str(), name));
+ },
+ CommandLine(lint_flag_val) => {
+ let flag = match level {
+ Warn => "-W", Deny => "-D", Forbid => "-F",
+ Allow => bug!("earlier conditional return should handle Allow case")
+ };
+ let hyphen_case_lint_name = name.replace("_", "-");
+ if lint_flag_val.as_str().deref() == name {
+ err.note(&format!("requested on the command line with `{} {}`",
+ flag, hyphen_case_lint_name));
+ } else {
+ let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-");
+ err.note(&format!("`{} {}` implied by `{} {}`",
+ flag, hyphen_case_lint_name, flag, hyphen_case_flag_val));
+ }
+ },
+ Node(lint_attr_name, src) => {
+ def = Some(src);
+ if lint_attr_name.as_str().deref() != name {
+ let level_str = level.as_str();
+ err.note(&format!("#[{}({})] implied by #[{}({})]",
+ level_str, name, level_str, lint_attr_name));
+ }
+ }
+ }
+
// Check for future incompatibility lints and issue a stronger warning.
if let Some(future_incompatible) = lints.future_incompatible(LintId::of(lint)) {
let explanation = format!("this was previously accepted by the compiler \
self.lookup_and_emit(lint, Some(span), msg);
}
- fn early_lint(&self, early_lint: EarlyLint) {
+ fn early_lint(&self, early_lint: &EarlyLint) {
let span = early_lint.diagnostic.span.primary_span().expect("early lint w/o primary span");
let mut err = self.struct_span_lint(early_lint.id.lint,
span,
}
};
+ let lint_attr_name = result.expect("lint attribute should be well-formed").0;
+
for (lint_id, level, span) in v {
let (now, now_source) = self.lints().get_level_source(lint_id);
if now == Forbid && level != Forbid {
diag_builder.span_label(span, &format!("overruled by previous forbid"));
match now_source {
LintSource::Default => &mut diag_builder,
- LintSource::Node(forbid_source_span) => {
+ LintSource::Node(_, forbid_source_span) => {
diag_builder.span_label(forbid_source_span,
&format!("`forbid` level set here"))
},
- LintSource::CommandLine => {
+ LintSource::CommandLine(_) => {
diag_builder.note("`forbid` lint level was set on command line")
}
}.emit()
let src = self.lints().get_level_source(lint_id).1;
self.level_stack().push((lint_id, (now, src)));
pushed += 1;
- self.mut_lints().set_level(lint_id, (level, Node(span)));
+ self.mut_lints().set_level(lint_id, (level, Node(lint_attr_name, span)));
}
}
}
// Output any lints that were previously added to the session.
fn visit_id(&mut self, id: ast::NodeId) {
- if let Some(lints) = self.sess().lints.borrow_mut().remove(&id) {
- debug!("LateContext::visit_id: id={:?} lints={:?}", id, lints);
- for early_lint in lints {
- self.early_lint(early_lint);
- }
+ let lints = self.sess().lints.borrow_mut().take(id);
+ for early_lint in lints.iter().chain(self.tables.lints.get(id)) {
+ debug!("LateContext::visit_id: id={:?} early_lint={:?}", id, early_lint);
+ self.early_lint(early_lint);
}
}
// If we missed any lints added to the session, then there's a bug somewhere
// in the iteration code.
- for (id, v) in tcx.sess.lints.borrow().iter() {
+ if let Some((id, v)) = tcx.sess.lints.borrow().get_any() {
for early_lint in v {
span_bug!(early_lint.diagnostic.span.clone(),
"unprocessed lint {:?} at {}",
// Visit the whole crate.
cx.with_lint_attrs(&krate.attrs, |cx| {
// Lints may be assigned to the whole crate.
- if let Some(lints) = cx.sess.lints.borrow_mut().remove(&ast::CRATE_NODE_ID) {
- for early_lint in lints {
- cx.early_lint(early_lint);
- }
+ let lints = cx.sess.lints.borrow_mut().take(ast::CRATE_NODE_ID);
+ for early_lint in lints {
+ cx.early_lint(&early_lint);
}
// since the root module isn't visited as an item (because it isn't an
// If we missed any lints added to the session, then there's a bug somewhere
// in the iteration code.
- for (_, v) in sess.lints.borrow().iter() {
+ for (_, v) in sess.lints.borrow().get_any() {
for early_lint in v {
span_bug!(early_lint.diagnostic.span.clone(), "unprocessed lint {:?}", early_lint);
}
}
}
+
+impl Encodable for LintId {
+ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+ s.emit_str(&self.lint.name.to_lowercase())
+ }
+}
+
+impl Decodable for LintId {
+ #[inline]
+ fn decode<D: Decoder>(d: &mut D) -> Result<LintId, D::Error> {
+ let s = d.read_str()?;
+ ty::tls::with(|tcx| {
+ match tcx.sess.lint_store.borrow().find_lint(&s, tcx.sess, None) {
+ Ok(id) => Ok(id),
+ Err(_) => panic!("invalid lint-id `{}`", s),
+ }
+ })
+ }
+}
pub use self::Level::*;
pub use self::LintSource::*;
+use hir;
+use hir::intravisit::FnKind;
use std::hash;
use std::ascii::AsciiExt;
use syntax_pos::Span;
-use hir::intravisit::FnKind;
use syntax::visit as ast_visit;
use syntax::ast;
-use hir;
+use syntax::symbol::Symbol;
pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore,
raw_emit_lint, check_crate, check_ast_crate, gather_attrs,
raw_struct_lint, FutureIncompatibleInfo, EarlyLint, IntoEarlyLint};
+pub use lint::table::LintTable;
+
/// Specification of a single lint.
#[derive(Copy, Clone, Debug)]
pub struct Lint {
Default,
/// Lint level was set by an attribute.
- Node(Span),
+ Node(ast::Name, Span),
/// Lint level was set by a command-line flag.
- CommandLine,
+ CommandLine(Symbol),
}
pub type LevelSource = (Level, LintSource);
pub mod builtin;
mod context;
+mod table;
--- /dev/null
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use syntax::ast;
+use syntax_pos::MultiSpan;
+use util::nodemap::NodeMap;
+
+use super::{Lint, LintId, EarlyLint, IntoEarlyLint};
+
+#[derive(RustcEncodable, RustcDecodable)]
+pub struct LintTable {
+ map: NodeMap<Vec<EarlyLint>>
+}
+
+impl LintTable {
+ pub fn new() -> Self {
+ LintTable { map: NodeMap() }
+ }
+
+ pub fn add_lint<S: Into<MultiSpan>>(&mut self,
+ lint: &'static Lint,
+ id: ast::NodeId,
+ sp: S,
+ msg: String)
+ {
+ self.add_lint_diagnostic(lint, id, (sp, &msg[..]))
+ }
+
+ pub fn add_lint_diagnostic<M>(&mut self,
+ lint: &'static Lint,
+ id: ast::NodeId,
+ msg: M)
+ where M: IntoEarlyLint,
+ {
+ let lint_id = LintId::of(lint);
+ let early_lint = msg.into_early_lint(lint_id);
+ let arr = self.map.entry(id).or_insert(vec![]);
+ if !arr.contains(&early_lint) {
+ arr.push(early_lint);
+ }
+ }
+
+ pub fn get(&self, id: ast::NodeId) -> &[EarlyLint] {
+ self.map.get(&id).map(|v| &v[..]).unwrap_or(&[])
+ }
+
+ pub fn take(&mut self, id: ast::NodeId) -> Vec<EarlyLint> {
+ self.map.remove(&id).unwrap_or(vec![])
+ }
+
+ pub fn transfer(&mut self, into: &mut LintTable) {
+ into.map.extend(self.map.drain());
+ }
+
+ /// Returns the first (id, lint) pair that is non-empty. Used to
+ /// implement a sanity check in lints that all node-ids are
+ /// visited.
+ pub fn get_any(&self) -> Option<(&ast::NodeId, &Vec<EarlyLint>)> {
+ self.map.iter()
+ .filter(|&(_, v)| !v.is_empty())
+ .next()
+ }
+}
+
use hir;
use rustc_back::PanicStrategy;
-pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown};
+pub use self::NativeLibraryKind::*;
// lonely orphan structs and enums looking for a better home
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub enum NativeLibraryKind {
NativeStatic, // native static library (.a archive)
+ NativeStaticNobundle, // native static library, which doesn't get bundled into .rlibs
NativeFramework, // OSX-specific
NativeUnknown, // default way to specify a dynamic library
}
PatKind::Tuple(ref subpats, ddpos) => {
// (p1, ..., pN)
let expected_len = match self.pat_ty(&pat)?.sty {
- ty::TyTuple(ref tys) => tys.len(),
+ ty::TyTuple(ref tys, _) => tys.len(),
ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty),
};
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
use syntax::symbol::keywords;
use syntax_pos::Span;
use errors::DiagnosticBuilder;
-use util::nodemap::{NodeMap, FxHashSet, FxHashMap, DefIdMap};
+use util::nodemap::{NodeMap, NodeSet, FxHashSet, FxHashMap, DefIdMap};
use rustc_back::slice;
use hir;
// `Region` describing how that region is bound
pub defs: NodeMap<Region>,
- // the set of lifetime def ids that are late-bound; late-bound ids
- // are named regions appearing in fn arguments that do not appear
- // in where-clauses
- pub late_bound: NodeMap<ty::Issue32330>,
+ // the set of lifetime def ids that are late-bound; a region can
+ // be late-bound if (a) it does NOT appear in a where-clause and
+ // (b) it DOES appear in the arguments.
+ pub late_bound: NodeSet,
+
+ // Contains the node-ids for lifetimes that were (incorrectly) categorized
+ // as late-bound, until #32330 was fixed.
+ pub issue_32330: NodeMap<ty::Issue32330>,
// For each type and trait definition, maps type parameters
// to the trait object lifetime defaults computed from them.
let krate = hir_map.krate();
let mut map = NamedRegionMap {
defs: NodeMap(),
- late_bound: NodeMap(),
+ late_bound: NodeSet(),
+ issue_32330: NodeMap(),
object_lifetime_defaults: compute_object_lifetime_defaults(sess, hir_map),
};
sess.track_errors(|| {
}
let lifetimes = generics.lifetimes.iter().map(|def| {
- if self.map.late_bound.contains_key(&def.lifetime.id) {
+ if self.map.late_bound.contains(&def.lifetime.id) {
Region::late(def)
} else {
Region::early(&mut index, def)
// just mark it so we can issue warnings.
let constrained_by_input = constrained_by_input.regions.contains(&name);
let appears_in_output = appears_in_output.regions.contains(&name);
- let will_change = !constrained_by_input && appears_in_output;
- let issue_32330 = if will_change {
- ty::Issue32330::WillChange {
- fn_def_id: fn_def_id,
- region_name: name,
- }
- } else {
- ty::Issue32330::WontChange
- };
+ if !constrained_by_input && appears_in_output {
+ debug!("inserting issue_32330 entry for {:?}, {:?} on {:?}",
+ lifetime.lifetime.id,
+ name,
+ fn_def_id);
+ map.issue_32330.insert(
+ lifetime.lifetime.id,
+ ty::Issue32330 {
+ fn_def_id: fn_def_id,
+ region_name: name,
+ });
+ continue;
+ }
debug!("insert_late_bound_lifetimes: \
- lifetime {:?} with id {:?} is late-bound ({:?}",
- lifetime.lifetime.name, lifetime.lifetime.id, issue_32330);
+ lifetime {:?} with id {:?} is late-bound",
+ lifetime.lifetime.name, lifetime.lifetime.id);
- let prev = map.late_bound.insert(lifetime.lifetime.id, issue_32330);
- assert!(prev.is_none(), "visited lifetime {:?} twice", lifetime.lifetime.id);
+ let inserted = map.late_bound.insert(lifetime.lifetime.id);
+ assert!(inserted, "visited lifetime {:?} twice", lifetime.lifetime.id);
}
return;
let lhs_ty = lhs.ty(mir, tcx);
let rhs_ty = rhs.ty(mir, tcx);
let ty = op.ty(tcx, lhs_ty, rhs_ty);
- let ty = tcx.intern_tup(&[ty, tcx.types.bool]);
+ let ty = tcx.intern_tup(&[ty, tcx.types.bool], false);
Some(ty)
}
&Rvalue::UnaryOp(_, ref operand) => {
}
AggregateKind::Tuple => {
Some(tcx.mk_tup(
- ops.iter().map(|op| op.ty(mir, tcx))
+ ops.iter().map(|op| op.ty(mir, tcx)),
+ false
))
}
AggregateKind::Adt(def, _, substs, _) => {
(Some(name), "dylib") => (name, cstore::NativeUnknown),
(Some(name), "framework") => (name, cstore::NativeFramework),
(Some(name), "static") => (name, cstore::NativeStatic),
+ (Some(name), "static-nobundle") => (name, cstore::NativeStaticNobundle),
(_, s) => {
early_error(error_format, &format!("unknown library kind `{}`, expected \
one of dylib, framework, or static",
s));
}
};
+ if kind == cstore::NativeStaticNobundle && !nightly_options::is_nightly_build() {
+ early_error(error_format, &format!("the library kind 'static-nobundle' is only \
+ accepted on the nightly compiler"));
+ }
let mut name_parts = name.splitn(2, ':');
let name = name_parts.next().unwrap();
let new_name = name_parts.next();
use session::search_paths::PathKind;
use session::config::DebugInfoLevel;
use ty::tls;
-use util::nodemap::{NodeMap, FxHashMap, FxHashSet};
+use util::nodemap::{FxHashMap, FxHashSet};
use util::common::duration_to_secs_str;
use mir::transform as mir_pass;
pub local_crate_source_file: Option<PathBuf>,
pub working_dir: PathBuf,
pub lint_store: RefCell<lint::LintStore>,
- pub lints: RefCell<NodeMap<Vec<lint::EarlyLint>>>,
+ pub lints: RefCell<lint::LintTable>,
/// Set of (LintId, span, message) tuples tracking lint (sub)diagnostics
/// that have been set once, but should not be set again, in order to avoid
/// redundantly verbose output (Issue #24690).
pub fn unimpl(&self, msg: &str) -> ! {
self.diagnostic().unimpl(msg)
}
+
pub fn add_lint<S: Into<MultiSpan>>(&self,
lint: &'static lint::Lint,
id: ast::NodeId,
sp: S,
msg: String)
{
- self.add_lint_diagnostic(lint, id, (sp, &msg[..]))
+ self.lints.borrow_mut().add_lint(lint, id, sp, msg);
}
pub fn add_lint_diagnostic<M>(&self,
msg: M)
where M: lint::IntoEarlyLint,
{
- let lint_id = lint::LintId::of(lint);
- let mut lints = self.lints.borrow_mut();
- let early_lint = msg.into_early_lint(lint_id);
- if let Some(arr) = lints.get_mut(&id) {
- if !arr.contains(&early_lint) {
- arr.push(early_lint);
- }
- return;
- }
- lints.insert(id, vec![early_lint]);
+ self.lints.borrow_mut().add_lint_diagnostic(lint, id, msg);
}
+
pub fn reserve_node_ids(&self, count: usize) -> ast::NodeId {
let id = self.next_node_id.get();
local_crate_source_file: local_crate_source_file,
working_dir: env::current_dir().unwrap(),
lint_store: RefCell::new(lint::LintStore::new()),
- lints: RefCell::new(NodeMap()),
+ lints: RefCell::new(lint::LintTable::new()),
one_time_diagnostics: RefCell::new(FxHashSet()),
plugin_llvm_passes: RefCell::new(Vec::new()),
mir_passes: RefCell::new(mir_pass::Passes::new()),
use std::cmp;
use std::fmt;
use syntax::ast;
+use hir::{intravisit, Local, Pat};
+use hir::intravisit::{Visitor, NestedVisitorMap};
use syntax_pos::{DUMMY_SP, Span};
use errors::DiagnosticBuilder;
}
}
+struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
+ infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+ target_ty: &'a Ty<'tcx>,
+ found_pattern: Option<&'a Pat>,
+}
+
+impl<'a, 'gcx, 'tcx> Visitor<'a> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
+ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
+ NestedVisitorMap::None
+ }
+
+ fn visit_local(&mut self, local: &'a Local) {
+ if let Some(&ty) = self.infcx.tables.borrow().node_types.get(&local.id) {
+ let ty = self.infcx.resolve_type_vars_if_possible(&ty);
+ let is_match = ty.walk().any(|t| t == *self.target_ty);
+
+ if is_match && self.found_pattern.is_none() {
+ self.found_pattern = Some(&*local.pat);
+ }
+ }
+ intravisit::walk_local(self, local);
+ }
+}
+
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
pub fn report_fulfillment_errors(&self, errors: &Vec<FulfillmentError<'tcx>>) {
for error in errors {
self.tcx.lang_items.sized_trait()
.map_or(false, |sized_id| sized_id == trait_ref.def_id())
{
- self.need_type_info(obligation.cause.span, self_ty);
+ self.need_type_info(obligation, self_ty);
} else {
let mut err = struct_span_err!(self.tcx.sess,
obligation.cause.span, E0283,
// Same hacky approach as above to avoid deluging user
// with error messages.
if !ty.references_error() && !self.tcx.sess.has_errors() {
- self.need_type_info(obligation.cause.span, ty);
+ self.need_type_info(obligation, ty);
}
}
})
}
-
- fn need_type_info(&self, span: Span, ty: Ty<'tcx>) {
- let ty = self.resolve_type_vars_if_possible(&ty);
- let name = if let ty::TyInfer(ty::TyVar(ty_vid)) = ty.sty {
+ fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String {
+ if let ty::TyInfer(ty::TyVar(ty_vid)) = (*ty).sty {
let ty_vars = self.type_variables.borrow();
if let TypeVariableOrigin::TypeParameterDefinition(_, name) =
- *ty_vars.var_origin(ty_vid)
- {
+ *ty_vars.var_origin(ty_vid) {
name.to_string()
} else {
ty.to_string()
}
} else {
ty.to_string()
+ }
+ }
+
+ fn need_type_info(&self, obligation: &PredicateObligation<'tcx>, ty: Ty<'tcx>) {
+ let ty = self.resolve_type_vars_if_possible(&ty);
+ let name = self.extract_type_name(&ty);
+ let ref cause = obligation.cause;
+
+ let mut err = struct_span_err!(self.tcx.sess,
+ cause.span,
+ E0282,
+ "type annotations needed");
+
+ err.span_label(cause.span, &format!("cannot infer type for `{}`", name));
+
+ let expr = self.tcx.hir.expect_expr(cause.body_id);
+
+ let mut local_visitor = FindLocalByTypeVisitor {
+ infcx: &self,
+ target_ty: &ty,
+ found_pattern: None,
};
- let mut err = struct_span_err!(self.tcx.sess, span, E0282,
- "unable to infer enough type information about `{}`",
- name);
- err.note("type annotations or generic parameter binding required");
- err.span_label(span, &format!("cannot infer type for `{}`", name));
+ local_visitor.visit_expr(expr);
+
+ if let Some(pattern) = local_visitor.found_pattern {
+ let pattern_span = pattern.span;
+ if let Some(simple_name) = pattern.simple_name() {
+ err.span_label(pattern_span,
+ &format!("consider giving `{}` a type",
+ simple_name));
+ } else {
+ err.span_label(pattern_span, &format!("consider giving a type to pattern"));
+ }
+ }
+
err.emit();
}
use std::rc::Rc;
use syntax::abi::Abi;
use hir;
+use lint;
use util::nodemap::FxHashMap;
struct InferredObligationsSnapshotVecDelegate<'tcx> {
debug!("select({:?})", obligation);
assert!(!obligation.predicate.has_escaping_regions());
+ let tcx = self.tcx();
let dep_node = obligation.predicate.dep_node();
- let _task = self.tcx().dep_graph.in_task(dep_node);
+ let _task = tcx.dep_graph.in_task(dep_node);
let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
- match self.candidate_from_obligation(&stack)? {
- None => Ok(None),
+ let ret = match self.candidate_from_obligation(&stack)? {
+ None => None,
Some(candidate) => {
let mut candidate = self.confirm_candidate(obligation, candidate)?;
let inferred_obligations = (*self.inferred_obligations).into_iter().cloned();
candidate.nested_obligations_mut().extend(inferred_obligations);
- Ok(Some(candidate))
+ Some(candidate)
},
+ };
+
+ // Test whether this is a `()` which was produced by defaulting a
+ // diverging type variable with `!` disabled. If so, we may need
+ // to raise a warning.
+ if obligation.predicate.skip_binder().self_ty().is_defaulted_unit() {
+ let mut raise_warning = true;
+ // Don't raise a warning if the trait is implemented for ! and only
+ // permits a trivial implementation for !. This stops us warning
+ // about (for example) `(): Clone` becoming `!: Clone` because such
+ // a switch can't cause code to stop compiling or execute
+ // differently.
+ let mut never_obligation = obligation.clone();
+ let def_id = never_obligation.predicate.skip_binder().trait_ref.def_id;
+ never_obligation.predicate = never_obligation.predicate.map_bound(|mut trait_pred| {
+ // Swap out () with ! so we can check if the trait is impld for !
+ {
+ let mut trait_ref = &mut trait_pred.trait_ref;
+ let unit_substs = trait_ref.substs;
+ let mut never_substs = Vec::with_capacity(unit_substs.len());
+ never_substs.push(From::from(tcx.types.never));
+ never_substs.extend(&unit_substs[1..]);
+ trait_ref.substs = tcx.intern_substs(&never_substs);
+ }
+ trait_pred
+ });
+ if let Ok(Some(..)) = self.select(&never_obligation) {
+ if !tcx.trait_relevant_for_never(def_id) {
+ // The trait is also implemented for ! and the resulting
+ // implementation cannot actually be invoked in any way.
+ raise_warning = false;
+ }
+ }
+
+ if raise_warning {
+ tcx.sess.add_lint(lint::builtin::RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
+ obligation.cause.body_id,
+ obligation.cause.span,
+ format!("code relies on type inference rules which are likely \
+ to change"));
+ }
}
+ Ok(ret)
}
///////////////////////////////////////////////////////////////////////////
ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) => Never,
- ty::TyTuple(tys) => {
+ ty::TyTuple(tys, _) => {
Where(ty::Binder(tys.last().into_iter().cloned().collect()))
}
let sized_crit = def.sized_constraint(self.tcx());
// (*) binder moved here
Where(ty::Binder(match sized_crit.sty {
- ty::TyTuple(tys) => tys.to_vec().subst(self.tcx(), substs),
+ ty::TyTuple(tys, _) => tys.to_vec().subst(self.tcx(), substs),
ty::TyBool => vec![],
_ => vec![sized_crit.subst(self.tcx(), substs)]
}))
Where(ty::Binder(vec![element_ty]))
}
- ty::TyTuple(tys) => {
+ ty::TyTuple(tys, _) => {
// (*) binder moved here
Where(ty::Binder(tys.to_vec()))
}
vec![element_ty]
}
- ty::TyTuple(ref tys) => {
+ ty::TyTuple(ref tys, _) => {
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
tys.to_vec()
}
let arguments_tuple = match tuple_arguments {
TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
TupleArgumentsFlag::Yes =>
- self.intern_tup(sig.skip_binder().inputs()),
+ self.intern_tup(sig.skip_binder().inputs(), false),
};
let trait_ref = ty::TraitRef {
def_id: fn_trait_def_id,
|ty| tc_ty(tcx, &ty, cache))
}
- ty::TyTuple(ref tys) => {
+ ty::TyTuple(ref tys, _) => {
TypeContents::union(&tys[..],
|ty| tc_ty(tcx, *ty, cache))
}
use dep_graph::{DepGraph, DepTrackingMap};
use session::Session;
+use lint;
use middle;
use hir::TraitMap;
use hir::def::Def;
/// Maps a cast expression to its kind. This is keyed on the
/// *from* expression of the cast, not the cast itself.
pub cast_kinds: NodeMap<ty::cast::CastKind>,
+
+ /// Lints for the body of this fn generated by typeck.
+ pub lints: lint::LintTable,
}
impl<'tcx> TypeckTables<'tcx> {
liberated_fn_sigs: NodeMap(),
fru_field_types: NodeMap(),
cast_kinds: NodeMap(),
+ lints: lint::LintTable::new(),
}
}
/// Set of trait imports actually used in the method resolution.
/// This is used for warning unused imports.
- pub used_trait_imports: RefCell<NodeSet>,
+ pub used_trait_imports: RefCell<DepTrackingMap<maps::UsedTraitImports<'tcx>>>,
/// The set of external nominal types whose implementations have been read.
/// This is used for lazy resolution of methods.
inherent_impls: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
used_unsafe: RefCell::new(NodeSet()),
used_mut_nodes: RefCell::new(NodeSet()),
- used_trait_imports: RefCell::new(NodeSet()),
+ used_trait_imports: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
populated_external_types: RefCell::new(DefIdSet()),
populated_external_primitive_impls: RefCell::new(DefIdSet()),
stability: RefCell::new(stability),
self.mk_ty(TySlice(ty))
}
- pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
- self.mk_ty(TyTuple(self.intern_type_list(ts)))
+ pub fn intern_tup(self, ts: &[Ty<'tcx>], defaulted: bool) -> Ty<'tcx> {
+ self.mk_ty(TyTuple(self.intern_type_list(ts), defaulted))
}
- pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I) -> I::Output {
- iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts))))
+ pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I,
+ defaulted: bool) -> I::Output {
+ iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts), defaulted)))
}
pub fn mk_nil(self) -> Ty<'tcx> {
- self.intern_tup(&[])
+ self.intern_tup(&[], false)
}
pub fn mk_diverging_default(self) -> Ty<'tcx> {
if self.sess.features.borrow().never_type {
self.types.never
} else {
- self.mk_nil()
+ self.intern_tup(&[], true)
}
}
match self.sty {
ty::TyBool | ty::TyChar | ty::TyInt(_) |
ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr | ty::TyNever => self.to_string(),
- ty::TyTuple(ref tys) if tys.is_empty() => self.to_string(),
+ ty::TyTuple(ref tys, _) if tys.is_empty() => self.to_string(),
ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
ty::TyArray(_, n) => format!("array of {} elements", n),
|p| format!("trait {}", tcx.item_path_str(p.def_id())))
}
ty::TyClosure(..) => "closure".to_string(),
- ty::TyTuple(_) => "tuple".to_string(),
+ ty::TyTuple(..) => "tuple".to_string(),
ty::TyInfer(ty::TyVar(_)) => "inferred type".to_string(),
ty::TyInfer(ty::IntVar(_)) => "integral variable".to_string(),
ty::TyInfer(ty::FloatVar(_)) => "floating-point variable".to_string(),
Some(ClosureSimplifiedType(def_id))
}
ty::TyNever => Some(NeverSimplifiedType),
- ty::TyTuple(ref tys) => {
+ ty::TyTuple(ref tys, _) => {
Some(TupleSimplifiedType(tys.len()))
}
ty::TyFnDef(.., ref f) | ty::TyFnPtr(ref f) => {
self.add_ty(m.ty);
}
- &ty::TyTuple(ref ts) => {
+ &ty::TyTuple(ref ts, _) => {
self.add_tys(&ts[..]);
}
},
TyNever => DefIdForest::full(tcx),
- TyTuple(ref tys) => {
+ TyTuple(ref tys, _) => {
DefIdForest::union(tcx, tys.iter().map(|ty| {
ty.uninhabited_from(visited, tcx)
}))
ty::TyRawPtr(mt) |
ty::TyRef(_, mt) => characteristic_def_id_of_type(mt.ty),
- ty::TyTuple(ref tys) => tys.iter()
- .filter_map(|ty| characteristic_def_id_of_type(ty))
- .next(),
+ ty::TyTuple(ref tys, _) => tys.iter()
+ .filter_map(|ty| characteristic_def_id_of_type(ty))
+ .next(),
ty::TyFnDef(def_id, ..) |
ty::TyClosure(def_id, _) => Some(def_id),
use syntax::ast::{FloatTy, IntTy, UintTy};
use syntax::attr;
use syntax_pos::DUMMY_SP;
-use rustc_i128::u128;
use rustc_const_math::ConstInt;
use std::cmp;
Some(&variant.memory_index[..]))
}
// Can we use one of the fields in this tuple?
- (&Univariant { ref variant, .. }, &ty::TyTuple(tys)) => {
+ (&Univariant { ref variant, .. }, &ty::TyTuple(tys, _)) => {
Struct::non_zero_field_paths(infcx, tys.iter().cloned(),
Some(&variant.memory_index[..]))
}
Univariant { variant: st, non_zero: false }
}
- ty::TyTuple(tys) => {
+ ty::TyTuple(tys, _) => {
// FIXME(camlorn): if we ever allow unsized tuples, this needs to be checked.
// See the univariant case below to learn how.
let st = Struct::new(dl,
use hir::def_id::DefId;
use mir;
use ty::{self, Ty};
+use util::nodemap::DefIdSet;
use std::cell::RefCell;
use std::marker::PhantomData;
dep_map_ty! { ClosureKinds: ItemSignature(DefId) -> ty::ClosureKind }
dep_map_ty! { ClosureTypes: ItemSignature(DefId) -> ty::ClosureTy<'tcx> }
dep_map_ty! { TypeckTables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx> }
+dep_map_ty! { UsedTraitImports: UsedTraitImports(DefId) -> DefIdSet }
AssociatedKind::Type => Def::AssociatedTy(self.def_id),
}
}
+
+ /// Tests whether the associated item admits a non-trivial implementation
+ /// for !
+ pub fn relevant_for_never<'tcx>(&self) -> bool {
+ match self.kind {
+ AssociatedKind::Const => true,
+ AssociatedKind::Type => true,
+ // FIXME(canndrew): Be more thorough here, check if any argument is uninhabited.
+ AssociatedKind::Method => !self.method_has_self_argument,
+ }
+ }
}
#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable)]
pub name: Name,
pub def_id: DefId,
pub index: u32,
+ pub issue_32330: Option<ty::Issue32330>,
/// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
/// on generic parameter `'a`, asserts data of lifetime `'a`
}
pub fn to_bound_region(&self) -> ty::BoundRegion {
- // this is an early bound region, so unaffected by #32330
- ty::BoundRegion::BrNamed(self.def_id, self.name, Issue32330::WontChange)
+ ty::BoundRegion::BrNamed(self.def_id, self.name)
}
}
_ if tys.references_error() => tcx.types.err,
0 => tcx.types.bool,
1 => tys[0],
- _ => tcx.intern_tup(&tys[..])
+ _ => tcx.intern_tup(&tys[..], false)
};
let old = tcx.adt_sized_constraint.borrow().get(&self.did).cloned();
vec![ty]
}
- TyTuple(ref tys) => {
+ TyTuple(ref tys, _) => {
match tys.last() {
None => vec![],
Some(ty) => self.sized_constraint_for_ty(tcx, stack, ty)
.subst(tcx, substs);
debug!("sized_constraint_for_ty({:?}) intermediate = {:?}",
ty, adt_ty);
- if let ty::TyTuple(ref tys) = adt_ty.sty {
+ if let ty::TyTuple(ref tys, _) = adt_ty.sty {
tys.iter().flat_map(|ty| {
self.sized_constraint_for_ty(tcx, stack, ty)
}).collect()
}
}
+ pub fn trait_relevant_for_never(self, did: DefId) -> bool {
+ self.associated_items(did).any(|item| {
+ item.relevant_for_never()
+ })
+ }
+
pub fn custom_coerce_unsized_kind(self, did: DefId) -> adjustment::CustomCoerceUnsized {
self.custom_coerce_unsized_kinds.memoize(did, || {
let (kind, src) = if did.krate != LOCAL_CRATE {
Ok(tcx.mk_slice(t))
}
- (&ty::TyTuple(as_), &ty::TyTuple(bs)) =>
+ (&ty::TyTuple(as_, a_defaulted), &ty::TyTuple(bs, b_defaulted)) =>
{
if as_.len() == bs.len() {
- Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)))?)
+ let defaulted = a_defaulted || b_defaulted;
+ Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)), defaulted)?)
} else if !(as_.is_empty() || bs.is_empty()) {
Err(TypeError::TupleSize(
expected_found(relation, &as_.len(), &bs.len())))
ty::TyAdt(tid, substs) => ty::TyAdt(tid, substs.fold_with(folder)),
ty::TyDynamic(ref trait_ty, ref region) =>
ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)),
- ty::TyTuple(ts) => ty::TyTuple(ts.fold_with(folder)),
+ ty::TyTuple(ts, defaulted) => ty::TyTuple(ts.fold_with(folder), defaulted),
ty::TyFnDef(def_id, substs, f) => {
ty::TyFnDef(def_id,
substs.fold_with(folder),
ty::TyAdt(_, substs) => substs.visit_with(visitor),
ty::TyDynamic(ref trait_ty, ref reg) =>
trait_ty.visit_with(visitor) || reg.visit_with(visitor),
- ty::TyTuple(ts) => ts.visit_with(visitor),
+ ty::TyTuple(ts, _) => ts.visit_with(visitor),
ty::TyFnDef(_, substs, ref f) => {
substs.visit_with(visitor) || f.visit_with(visitor)
}
///
/// The def-id is needed to distinguish free regions in
/// the event of shadowing.
- BrNamed(DefId, Name, Issue32330),
+ BrNamed(DefId, Name),
/// Fresh bound identifiers created during GLB computations.
BrFresh(u32),
BrEnv
}
-/// True if this late-bound region is unconstrained, and hence will
-/// become early-bound once #32330 is fixed.
+/// When a region changed from late-bound to early-bound when #32330
+/// was fixed, its `RegionParameterDef` will have one of these
+/// structures that we can use to give nicer errors.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash,
RustcEncodable, RustcDecodable)]
-pub enum Issue32330 {
- WontChange,
+pub struct Issue32330 {
+ /// fn where is region declared
+ pub fn_def_id: DefId,
- /// this region will change from late-bound to early-bound once
- /// #32330 is fixed.
- WillChange {
- /// fn where is region declared
- fn_def_id: DefId,
-
- /// name of region; duplicates the info in BrNamed but convenient
- /// to have it here, and this code is only temporary
- region_name: ast::Name,
- }
+ /// name of region; duplicates the info in BrNamed but convenient
+ /// to have it here, and this code is only temporary
+ pub region_name: ast::Name,
}
// NB: If you change this, you'll probably want to change the corresponding
TyNever,
/// A tuple type. For example, `(i32, bool)`.
- TyTuple(&'tcx Slice<Ty<'tcx>>),
+ /// The bool indicates whether this is a unit tuple and was created by
+ /// defaulting a diverging type variable with feature(never_type) disabled.
+ /// It's only purpose is for raising future-compatibility warnings for when
+ /// diverging type variables start defaulting to ! instead of ().
+ TyTuple(&'tcx Slice<Ty<'tcx>>, bool),
/// The projection of an associated type. For example,
/// `<T as Trait<..>>::N`.
pub fn is_nil(&self) -> bool {
match self.sty {
- TyTuple(ref tys) => tys.is_empty(),
+ TyTuple(ref tys, _) => tys.is_empty(),
_ => false
}
}
}
}
+ // Test whether this is a `()` which was produced by defaulting a
+ // diverging type variable with feature(never_type) disabled.
+ pub fn is_defaulted_unit(&self) -> bool {
+ match self.sty {
+ TyTuple(_, true) => true,
+ _ => false,
+ }
+ }
+
/// Checks whether a type is visibly uninhabited from a particular module.
/// # Example
/// ```rust
TySlice(_) |
TyRawPtr(_) |
TyNever |
- TyTuple(_) |
+ TyTuple(..) |
TyParam(_) |
TyInfer(_) |
TyError => {
// Don't use `struct_variant`, this may be a univariant enum.
adt.variants[0].fields.get(i).map(|f| f.ty(self, substs))
}
- (&TyTuple(ref v), None) => v.get(i).cloned(),
+ (&TyTuple(ref v, _), None) => v.get(i).cloned(),
_ => None
}
}
self.def_id(d);
}
}
- TyTuple(tys) => {
+ TyTuple(tys, defaulted) => {
self.hash(tys.len());
+ self.hash(defaulted);
}
TyParam(p) => {
self.hash(p.idx);
seen: &mut Vec<Ty<'tcx>>, ty: Ty<'tcx>)
-> Representability {
match ty.sty {
- TyTuple(ref ts) => {
+ TyTuple(ref ts, _) => {
find_nonrepresentable(tcx, sp, seen, ts.iter().cloned())
}
// Fixed-length vectors.
ty::TyClosure(_, ref substs) => {
stack.extend(substs.substs.types().rev());
}
- ty::TyTuple(ts) => {
+ ty::TyTuple(ts, _) => {
stack.extend(ts.iter().cloned().rev());
}
ty::TyFnDef(_, substs, ref ft) => {
self.require_sized(subty, traits::SliceOrArrayElem);
}
- ty::TyTuple(ref tys) => {
+ ty::TyTuple(ref tys, _) => {
if let Some((_last, rest)) = tys.split_last() {
for elem in rest {
self.require_sized(elem, traits::TupleElem);
// https://github.com/rust-lang/rust/issues/25505#issuecomment-102876737
pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf {
if !cfg!(windows) {
- return p.to_path_buf()
+ return p.to_path_buf();
}
let mut components = p.components();
let prefix = match components.next() {
pub enum LinkOrCopy {
Link,
- Copy
+ Copy,
}
/// Copy `p` into `q`, preferring to use hard-linking if possible. If
Err(_) => {
match fs::copy(p, q) {
Ok(_) => Ok(LinkOrCopy::Copy),
- Err(e) => Err(e)
+ Err(e) => Err(e),
+ }
+ }
+ }
+}
+
+#[derive(Debug)]
+pub enum RenameOrCopyRemove {
+ Rename,
+ CopyRemove,
+}
+
+/// Rename `p` into `q`, preferring to use `rename` if possible.
+/// If `rename` fails (rename may fail for reasons such as crossing
+/// filesystem), fallback to copy & remove
+pub fn rename_or_copy_remove<P: AsRef<Path>, Q: AsRef<Path>>(p: P,
+ q: Q)
+ -> io::Result<RenameOrCopyRemove> {
+ let p = p.as_ref();
+ let q = q.as_ref();
+ match fs::rename(p, q) {
+ Ok(()) => Ok(RenameOrCopyRemove::Rename),
+ Err(_) => {
+ match fs::copy(p, q) {
+ Ok(_) => {
+ fs::remove_file(p)?;
+ Ok(RenameOrCopyRemove::CopyRemove)
+ }
+ Err(e) => Err(e),
}
}
}
}
match path.parent() {
Some(p) => try!(create_dir_racy(p)),
- None => return Err(io::Error::new(io::ErrorKind::Other,
- "failed to create whole tree")),
+ None => return Err(io::Error::new(io::ErrorKind::Other, "failed to create whole tree")),
}
match fs::create_dir(path) {
Ok(()) => Ok(()),
+++ /dev/null
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub trait ToPrimitive {
- fn to_i8(&self) -> Option<i8>;
- fn to_i16(&self) -> Option<i16>;
- fn to_i32(&self) -> Option<i32>;
- fn to_i64(&self) -> Option<i64>;
- fn to_u8(&self) -> Option<u8>;
- fn to_u16(&self) -> Option<u16>;
- fn to_u32(&self) -> Option<u32>;
- fn to_u64(&self) -> Option<u64>;
-}
-
-impl ToPrimitive for i64 {
- fn to_i8(&self) -> Option<i8> {
- if *self < i8::min_value() as i64 || *self > i8::max_value() as i64 {
- None
- } else {
- Some(*self as i8)
- }
- }
- fn to_i16(&self) -> Option<i16> {
- if *self < i16::min_value() as i64 || *self > i16::max_value() as i64 {
- None
- } else {
- Some(*self as i16)
- }
- }
- fn to_i32(&self) -> Option<i32> {
- if *self < i32::min_value() as i64 || *self > i32::max_value() as i64 {
- None
- } else {
- Some(*self as i32)
- }
- }
- fn to_i64(&self) -> Option<i64> {
- Some(*self)
- }
- fn to_u8(&self) -> Option<u8> {
- if *self < 0 || *self > u8::max_value() as i64 {
- None
- } else {
- Some(*self as u8)
- }
- }
- fn to_u16(&self) -> Option<u16> {
- if *self < 0 || *self > u16::max_value() as i64 {
- None
- } else {
- Some(*self as u16)
- }
- }
- fn to_u32(&self) -> Option<u32> {
- if *self < 0 || *self > u32::max_value() as i64 {
- None
- } else {
- Some(*self as u32)
- }
- }
- fn to_u64(&self) -> Option<u64> {
- if *self < 0 {None} else {Some(*self as u64)}
- }
-}
-
-impl ToPrimitive for u64 {
- fn to_i8(&self) -> Option<i8> {
- if *self > i8::max_value() as u64 {None} else {Some(*self as i8)}
- }
- fn to_i16(&self) -> Option<i16> {
- if *self > i16::max_value() as u64 {None} else {Some(*self as i16)}
- }
- fn to_i32(&self) -> Option<i32> {
- if *self > i32::max_value() as u64 {None} else {Some(*self as i32)}
- }
- fn to_i64(&self) -> Option<i64> {
- if *self > i64::max_value() as u64 {None} else {Some(*self as i64)}
- }
- fn to_u8(&self) -> Option<u8> {
- if *self > u8::max_value() as u64 {None} else {Some(*self as u8)}
- }
- fn to_u16(&self) -> Option<u16> {
- if *self > u16::max_value() as u64 {None} else {Some(*self as u16)}
- }
- fn to_u32(&self) -> Option<u32> {
- if *self > u32::max_value() as u64 {None} else {Some(*self as u32)}
- }
- fn to_u64(&self) -> Option<u64> {
- Some(*self)
- }
-}
if !verbose && fn_trait_kind.is_some() && projections.len() == 1 {
let projection_ty = projections[0].ty;
- if let TyTuple(ref args) = substs.type_at(1).sty {
+ if let TyTuple(ref args, _) = substs.type_at(1).sty {
return fn_sig(f, args, false, projection_ty);
}
}
let new_value = tcx.replace_late_bound_regions(&value, |br| {
let _ = start_or_continue(f, "for<", ", ");
let br = match br {
- ty::BrNamed(_, name, _) => {
+ ty::BrNamed(_, name) => {
let _ = write!(f, "{}", name);
br
}
let name = Symbol::intern("'r");
let _ = write!(f, "{}", name);
ty::BrNamed(tcx.hir.local_def_id(CRATE_NODE_ID),
- name,
- ty::Issue32330::WontChange)
+ name)
}
};
tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), br))
}
match *self {
- BrNamed(_, name, _) => write!(f, "{}", name),
+ BrNamed(_, name) => write!(f, "{}", name),
BrAnon(_) | BrFresh(_) | BrEnv => Ok(())
}
}
match *self {
BrAnon(n) => write!(f, "BrAnon({:?})", n),
BrFresh(n) => write!(f, "BrFresh({:?})", n),
- BrNamed(did, name, issue32330) => {
- write!(f, "BrNamed({:?}:{:?}, {:?}, {:?})",
- did.krate, did.index, name, issue32330)
+ BrNamed(did, name) => {
+ write!(f, "BrNamed({:?}:{:?}, {:?})",
+ did.krate, did.index, name)
}
BrEnv => "BrEnv".fmt(f),
}
write!(f, "{}", tm)
}
TyNever => write!(f, "!"),
- TyTuple(ref tys) => {
+ TyTuple(ref tys, _) => {
write!(f, "(")?;
let mut tys = tys.iter();
if let Some(&ty) = tys.next() {
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::{Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+ let mut base = super::freebsd_base::opts();
+ base.max_atomic_width = Some(128);
+
+ // see #36994
+ base.exe_allocation_crate = "alloc_system".to_string();
+
+ Ok(Target {
+ llvm_target: "aarch64-unknown-freebsd".to_string(),
+ target_endian: "little".to_string(),
+ target_pointer_width: "64".to_string(),
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
+ arch: "aarch64".to_string(),
+ target_os: "freebsd".to_string(),
+ target_env: "".to_string(),
+ target_vendor: "unknown".to_string(),
+ options: TargetOptions {
+ abi_blacklist: super::arm_base::abi_blacklist(),
+ .. base
+ },
+ })
+}
linker_is_gnu: true,
allow_asm: false,
obj_is_bitcode: true,
+ is_like_emscripten: true,
max_atomic_width: Some(32),
post_link_args: vec!["-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()],
target_family: Some("unix".to_string()),
("armv7-linux-androideabi", armv7_linux_androideabi),
("aarch64-linux-android", aarch64_linux_android),
+ ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
("i686-unknown-freebsd", i686_unknown_freebsd),
("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
/// Whether the target toolchain is like Android's. Only useful for compiling against Android.
/// Defaults to false.
pub is_like_android: bool,
+ /// Whether the target toolchain is like Emscripten's. Only useful for compiling with
+ /// Emscripten toolchain.
+ /// Defaults to false.
+ pub is_like_emscripten: bool,
/// Whether the linker support GNU-like arguments such as -O. Defaults to false.
pub linker_is_gnu: bool,
/// The MinGW toolchain has a known issue that prevents it from correctly
is_like_solaris: false,
is_like_windows: false,
is_like_android: false,
+ is_like_emscripten: false,
is_like_msvc: false,
linker_is_gnu: false,
allows_weak_linkage: true,
key!(is_like_solaris, bool);
key!(is_like_windows, bool);
key!(is_like_msvc, bool);
+ key!(is_like_emscripten, bool);
key!(is_like_android, bool);
key!(linker_is_gnu, bool);
key!(allows_weak_linkage, bool);
target_option_val!(is_like_solaris);
target_option_val!(is_like_windows);
target_option_val!(is_like_msvc);
+ target_option_val!(is_like_emscripten);
target_option_val!(is_like_android);
target_option_val!(linker_is_gnu);
target_option_val!(allows_weak_linkage);
linker_is_gnu: true,
allow_asm: false,
obj_is_bitcode: true,
+ is_like_emscripten: true,
max_atomic_width: Some(32),
post_link_args: vec!["-s".to_string(), "BINARYEN=1".to_string(),
"-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()],
};
match parent_ty.sty {
- ty::TyTuple(ref v) => {
+ ty::TyTuple(ref v, _) => {
let tuple_idx = match *origin_field_name {
mc::PositionalField(tuple_idx) => tuple_idx,
mc::NamedField(_) =>
let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx).collect();
self.open_drop_for_tuple(c, &tys)
}
- ty::TyTuple(tys) => {
+ ty::TyTuple(tys, _) => {
self.open_drop_for_tuple(c, tys)
}
ty::TyAdt(def, _) if def.is_box() => {
syntax = { path = "../libsyntax" }
graphviz = { path = "../libgraphviz" }
syntax_pos = { path = "../libsyntax_pos" }
-rustc_i128 = { path = "../librustc_i128" }
fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usize {
debug!("constructor_arity({:?}, {:?})", ctor, ty);
match ty.sty {
- ty::TyTuple(ref fs) => fs.len(),
+ ty::TyTuple(ref fs, _) => fs.len(),
ty::TySlice(..) | ty::TyArray(..) => match *ctor {
Slice(length) => length,
ConstantValue(_) => 0,
{
debug!("constructor_sub_pattern_tys({:?}, {:?})", ctor, ty);
match ty.sty {
- ty::TyTuple(ref fs) => fs.into_iter().map(|t| *t).collect(),
+ ty::TyTuple(ref fs, _) => fs.into_iter().map(|t| *t).collect(),
ty::TySlice(ty) | ty::TyArray(ty, _) => match *ctor {
Slice(length) => repeat(ty).take(length).collect(),
ConstantValue(_) => vec![],
let mut seen = Matrix::empty();
let mut catchall = None;
let mut printed_if_let_err = false;
- for &(ref pats, guard) in arms {
+ for (arm_index, &(ref pats, guard)) in arms.iter().enumerate() {
for &(pat, hir_pat) in pats {
let v = vec![pat];
let &(ref first_arm_pats, _) = &arms[0];
let first_pat = &first_arm_pats[0];
let span = first_pat.0.span;
- struct_span_err!(cx.tcx.sess, span, E0165,
- "irrefutable while-let pattern")
- .span_label(span, &format!("irrefutable pattern"))
- .emit();
+
+ // check which arm we're on.
+ match arm_index {
+ // The arm with the user-specified pattern.
+ 0 => {
+ let mut diagnostic = Diagnostic::new(Level::Warning,
+ "unreachable pattern");
+ diagnostic.set_span(pat.span);
+ cx.tcx.sess.add_lint_diagnostic(
+ lint::builtin::UNREACHABLE_PATTERNS,
+ hir_pat.id, diagnostic);
+ },
+ // The arm with the wildcard pattern.
+ 1 => {
+ struct_span_err!(cx.tcx.sess, span, E0165,
+ "irrefutable while-let pattern")
+ .span_label(span, &format!("irrefutable pattern"))
+ .emit();
+ },
+ _ => bug!(),
+ }
},
hir::MatchSource::ForLoopDesugar |
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//#![allow(non_camel_case_types)]
-
use rustc::middle::const_val::ConstVal::*;
use rustc::middle::const_val::ConstVal;
use self::ErrKind::*;
use rustc_const_math::*;
use rustc_errors::DiagnosticBuilder;
-use rustc_i128::{i128, u128};
-
macro_rules! math {
($e:expr, $op:expr) => {
match $op {
(&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => {
return Ok(Integral(I64(i64::min_value())))
},
- (&LitKind::Int(n, _), Some(&ty::TyInt(IntTy::I128))) |
- (&LitKind::Int(n, Signed(IntTy::I128)), _) => {
- // SNAP: replace n in pattern with I128_OVERFLOW and remove this if.
- if n == I128_OVERFLOW {
- return Ok(Integral(I128(i128::min_value())))
- }
+ (&LitKind::Int(I128_OVERFLOW, _), Some(&ty::TyInt(IntTy::I128))) |
+ (&LitKind::Int(I128_OVERFLOW, Signed(IntTy::I128)), _) => {
+ return Ok(Integral(I128(i128::min_value())))
},
(&LitKind::Int(n, _), Some(&ty::TyInt(IntTy::Is))) |
(&LitKind::Int(n, Signed(IntTy::Is)), _) => {
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(const_fn)]
+#![feature(i128_type)]
extern crate arena;
#[macro_use] extern crate syntax;
extern crate graphviz;
extern crate syntax_pos;
-extern crate rustc_i128;
-
// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
pub mod diagnostics;
PatKind::Tuple(ref subpatterns, ddpos) => {
let ty = self.tables.node_id_to_type(pat.id);
match ty.sty {
- ty::TyTuple(ref tys) => {
+ ty::TyTuple(ref tys, _) => {
let subpatterns =
subpatterns.iter()
.enumerate_and_adjust(tys.len(), ddpos)
[dependencies]
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
-rustc_i128 = { path = "../librustc_i128" }
use std::cmp::Ordering;
use syntax::attr::IntType;
use syntax::ast::{IntTy, UintTy};
-use rustc_i128::{i128, u128};
use super::is::*;
use super::us::*;
mod ubounds {
#![allow(dead_code)]
- use rustc_i128::{u128, i128};
bounds!{u128: 0,
i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX
u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX u64 U64MIN U64MAX u128 U128MIN U128MAX
mod ibounds {
#![allow(dead_code)]
- use rustc_i128::i128;
- #[cfg(stage0)]
- pub const U64MIN: i128 = 0;
- #[cfg(stage0)]
- pub const U64MAX: i128 = i128::max_value();
- #[cfg(not(stage0))]
bounds!(i128, u64 U64MIN U64MAX);
pub const U128MIN: i128 = 0;
(InferSigned(a @ 0...ibounds::U8MAX), U8(_)) => U8(a as u8),
(InferSigned(a @ 0...ibounds::U16MAX), U16(_)) => U16(a as u16),
(InferSigned(a @ 0...ibounds::U32MAX), U32(_)) => U32(a as u32),
- // SNAP: replace with U64MAX
- (InferSigned(a @ 0...ibounds::I64MAX), U64(_)) => U64(a as u64),
+ (InferSigned(a @ 0...ibounds::U64MAX), U64(_)) => U64(a as u64),
(InferSigned(a @ 0...ibounds::I128MAX), U128(_)) => U128(a as u128),
(InferSigned(a @ 0...ibounds::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)),
(InferSigned(a @ 0...ibounds::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)),
- // SNAP: replace with U64MAX
- (InferSigned(a @ 0...ibounds::I64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)),
+ (InferSigned(a @ 0...ibounds::U64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)),
(InferSigned(_), _) => return Err(ConstMathErr::NotInRange),
_ => self, // already known types
};
derive_binop!(BitOr, bitor);
derive_binop!(BitXor, bitxor);
-#[cfg(not(stage0))]
const I128_MIN: i128 = ::std::i128::MIN;
-#[cfg(stage0)]
-const I128_MIN: i128 = ::std::i64::MIN;
fn check_division(
lhs: ConstInt,
use syntax::ast;
use super::err::*;
-use rustc_i128::i128;
/// Depending on the target only one variant is ever used in a compilation.
/// Anything else is an error. This invariant is checked at several locations
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(const_fn)]
-#![cfg_attr(not(stage0), feature(i128))]
+#![feature(i128)]
+#![feature(i128_type)]
extern crate syntax;
-// SNAP: remove use of this crate
-extern crate rustc_i128;
-
extern crate serialize as rustc_serialize; // used by deriving
mod float;
use syntax::ast;
use super::err::*;
-use rustc_i128::u128;
/// Depending on the target only one variant is ever used in a compilation.
/// Anything else is an error. This invariant is checked at several locations
[dependencies]
log = { path = "../liblog" }
serialize = { path = "../libserialize" }
-rustc_i128 = { path = "../librustc_i128" }
#![feature(untagged_unions)]
#![feature(associated_consts)]
#![feature(unsize)]
+#![feature(i128_type)]
#![cfg_attr(unix, feature(libc))]
#![cfg_attr(test, feature(test))]
#[cfg(unix)]
extern crate libc;
-extern crate rustc_i128;
-
pub use rustc_serialize::hex::ToHex;
pub mod array_vec;
use std::mem;
use blake2b::Blake2bHasher;
use rustc_serialize::leb128;
-use rustc_i128::{u128,i128};
fn write_unsigned_leb128_to_buf(buf: &mut [u8; 16], value: u64) -> usize {
leb128::write_unsigned_leb128_to(value as u128, |i, v| buf[i] = v)
use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
use rustc::util::common::time;
use rustc::util::nodemap::{NodeSet, NodeMap};
+use rustc::util::fs::rename_or_copy_remove;
use rustc_borrowck as borrowck;
use rustc_incremental::{self, IncrementalHashesMap};
use rustc_incremental::ich::Fingerprint;
"checking for inline asm in case the target doesn't support it",
|| no_asm::check_crate(sess, &krate));
- time(sess.time_passes(),
+ time(time_passes,
"early lint checks",
|| lint::check_ast_crate(sess, &krate));
- time(sess.time_passes(),
+ time(time_passes,
"AST validation",
|| ast_validation::check_crate(sess, &krate));
- time(sess.time_passes(), "name resolution", || -> CompileResult {
+ time(time_passes, "name resolution", || -> CompileResult {
// Since import resolution will eventually happen in expansion,
// don't perform `after_expand` until after import resolution.
after_expand(&krate)?;
})?;
// Lower ast -> hir.
- let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || {
+ let hir_forest = time(time_passes, "lowering ast -> hir", || {
let hir_crate = lower_crate(sess, &krate, &mut resolver);
if sess.opts.debugging_opts.hir_stats {
hir_map::Forest::new(hir_crate, &sess.dep_graph)
});
- // Discard hygiene data, which isn't required past lowering to HIR.
+ // Discard hygiene data, which isn't required after lowering to HIR.
if !keep_hygiene_data(sess) {
syntax::ext::hygiene::reset_hygiene_data();
}
// are going to build an executable
if sess.opts.output_types.contains_key(&OutputType::Exe) {
let f = outputs.path(OutputType::Object);
- fs::copy(&f,
+ rename_or_copy_remove(&f,
f.with_file_name(format!("{}.0.o",
f.file_stem().unwrap().to_string_lossy()))).unwrap();
- fs::remove_file(f).unwrap();
}
// Remove assembly source, unless --save-temps was specified
}
pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> {
- self.infcx.tcx.intern_tup(&[ty1, ty2])
+ self.infcx.tcx.intern_tup(&[ty1, ty2], false)
}
pub fn t_param(&self, index: u32) -> Ty<'tcx> {
let tcx = env.infcx.tcx;
let int_ty = tcx.types.isize;
let uint_ty = tcx.types.usize;
- let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty]);
- let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty]);
+ let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty], false);
+ let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty], false);
let walked: Vec<_> = tup2_ty.walk().collect();
assert_eq!(walked,
[tup2_ty, tup1_ty, int_ty, uint_ty, int_ty, uint_ty, tup1_ty, int_ty,
let tcx = env.infcx.tcx;
let int_ty = tcx.types.isize;
let uint_ty = tcx.types.usize;
- let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty]);
- let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty]);
+ let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty], false);
+ let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty], false);
// types we expect to see (in order), plus a boolean saying
// whether to skip the subtree.
crate-type = ["dylib"]
[dependencies]
+serialize = { path = "../libserialize" }
syntax_pos = { path = "../libsyntax_pos" }
use snippet::Style;
#[must_use]
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Diagnostic {
pub level: Level,
pub message: Vec<(String, Style)>,
}
/// For example a note attached to an error.
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct SubDiagnostic {
pub level: Level,
pub message: Vec<(String, Style)>,
extern crate term;
extern crate libc;
+extern crate serialize as rustc_serialize;
extern crate syntax_pos;
pub use emitter::ColorConfig;
use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION};
use syntax_pos::MacroBacktrace;
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub enum RenderSpan {
/// A FullSpan renders with both with an initial line for the
/// message, prefixed by file:linenum, followed by a summary of
Suggestion(CodeSuggestion),
}
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct CodeSuggestion {
pub msp: MultiSpan,
pub substitutes: Vec<String>,
}
-#[derive(Copy, PartialEq, Clone, Debug)]
+#[derive(Copy, PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum Level {
Bug,
Fatal,
pub style: Style,
}
-#[derive(Copy, Clone, Debug, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub enum Style {
HeaderMsg,
FileNameStyle,
+++ /dev/null
-[package]
-authors = ["The Rust Project Developers"]
-name = "rustc_i128"
-version = "0.0.0"
-
-[lib]
-name = "rustc_i128"
-path = "lib.rs"
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-#![allow(non_camel_case_types)]
-#![cfg_attr(not(stage0), feature(i128_type))]
-#![no_std]
-#![crate_type="rlib"]
-#![crate_name="rustc_i128"]
-
-#[cfg(stage0)]
-pub type i128 = i64;
-#[cfg(stage0)]
-pub type u128 = u64;
-
-#[cfg(not(stage0))]
-pub type i128 = int::_i128;
-#[cfg(not(stage0))]
-pub type u128 = int::_u128;
-#[cfg(not(stage0))]
-mod int {
- pub type _i128 = i128;
- pub type _u128 = u128;
-}
#![feature(staged_api)]
#![feature(rand)]
#![feature(core_intrinsics)]
+#![feature(conservative_impl_trait)]
+#![feature(field_init_shorthand)]
+#![feature(pub_restricted)]
extern crate graphviz;
#[macro_use] extern crate rustc;
/// Data for use when recompiling the **current crate**.
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct SerializedDepGraph {
- pub edges: Vec<SerializedEdge>,
+ pub edges: Vec<SerializedEdgeSet>,
/// These are hashes of two things:
/// - the HIR nodes in this crate
pub hashes: Vec<SerializedHash>,
}
-/// Represents a "reduced" dependency edge. Unlike the full dep-graph,
-/// the dep-graph we serialize contains only edges `S -> T` where the
-/// source `S` is something hashable (a HIR node or foreign metadata)
-/// and the target `T` is something significant, like a work-product.
-/// Normally, significant nodes are only those that have saved data on
-/// disk, but in unit-testing the set of significant nodes can be
-/// increased.
-pub type SerializedEdge = (DepNode<DefPathIndex>, DepNode<DefPathIndex>);
+/// Represents a set of "reduced" dependency edge. We group the
+/// outgoing edges from a single source together.
+#[derive(Debug, RustcEncodable, RustcDecodable)]
+pub struct SerializedEdgeSet {
+ pub source: DepNode<DefPathIndex>,
+ pub targets: Vec<DepNode<DefPathIndex>>
+}
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct SerializedHash {
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::hir::intravisit;
use syntax::ast::{self, Attribute, NestedMetaItem};
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
use syntax_pos::Span;
let _ignore = tcx.dep_graph.in_ignore();
let dirty_inputs: FxHashSet<DepNode<DefId>> =
- dirty_inputs.iter()
- .filter_map(|d| retraced.map(d))
- .collect();
+ dirty_inputs.keys()
+ .filter_map(|d| retraced.map(d))
+ .collect();
let query = tcx.dep_graph.query();
debug!("query-nodes: {:?}", query.nodes());
let krate = tcx.hir.krate();
- krate.visit_all_item_likes(&mut DirtyCleanVisitor {
+ let mut dirty_clean_visitor = DirtyCleanVisitor {
tcx: tcx,
query: &query,
dirty_inputs: dirty_inputs,
- });
+ checked_attrs: FxHashSet(),
+ };
+ krate.visit_all_item_likes(&mut dirty_clean_visitor);
+
+ let mut all_attrs = FindAllAttrs {
+ tcx: tcx,
+ attr_names: vec![ATTR_DIRTY, ATTR_CLEAN],
+ found_attrs: vec![],
+ };
+ intravisit::walk_crate(&mut all_attrs, krate);
+
+ // Note that we cannot use the existing "unused attribute"-infrastructure
+ // here, since that is running before trans. This is also the reason why
+ // all trans-specific attributes are `Whitelisted` in syntax::feature_gate.
+ all_attrs.report_unchecked_attrs(&dirty_clean_visitor.checked_attrs);
}
pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
query: &'a DepGraphQuery<DefId>,
dirty_inputs: FxHashSet<DepNode<DefId>>,
+ checked_attrs: FxHashSet<ast::AttrId>,
}
impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
dep_node.map_def(|&def_id| Some(self.tcx.item_path_str(def_id))).unwrap()
}
- fn assert_dirty(&self, item: &hir::Item, dep_node: DepNode<DefId>) {
+ fn assert_dirty(&self, item_span: Span, dep_node: DepNode<DefId>) {
debug!("assert_dirty({:?})", dep_node);
match dep_node {
if !self.dirty_inputs.contains(&dep_node) {
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx.sess.span_err(
- item.span,
+ item_span,
&format!("`{:?}` not found in dirty set, but should be dirty",
dep_node_str));
}
if self.query.contains_node(&dep_node) {
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx.sess.span_err(
- item.span,
+ item_span,
&format!("`{:?}` found in dep graph, but should be dirty", dep_node_str));
}
}
}
}
- fn assert_clean(&self, item: &hir::Item, dep_node: DepNode<DefId>) {
+ fn assert_clean(&self, item_span: Span, dep_node: DepNode<DefId>) {
debug!("assert_clean({:?})", dep_node);
match dep_node {
if self.dirty_inputs.contains(&dep_node) {
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx.sess.span_err(
- item.span,
+ item_span,
&format!("`{:?}` found in dirty-node set, but should be clean",
dep_node_str));
}
if !self.query.contains_node(&dep_node) {
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx.sess.span_err(
- item.span,
+ item_span,
&format!("`{:?}` not found in dep graph, but should be clean",
dep_node_str));
}
}
}
}
-}
-impl<'a, 'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'a, 'tcx> {
- fn visit_item(&mut self, item: &'tcx hir::Item) {
- let def_id = self.tcx.hir.local_def_id(item.id);
+ fn check_item(&mut self, item_id: ast::NodeId, item_span: Span) {
+ let def_id = self.tcx.hir.local_def_id(item_id);
for attr in self.tcx.get_attrs(def_id).iter() {
if attr.check_name(ATTR_DIRTY) {
if check_config(self.tcx, attr) {
- self.assert_dirty(item, self.dep_node(attr, def_id));
+ self.checked_attrs.insert(attr.id);
+ self.assert_dirty(item_span, self.dep_node(attr, def_id));
}
} else if attr.check_name(ATTR_CLEAN) {
if check_config(self.tcx, attr) {
- self.assert_clean(item, self.dep_node(attr, def_id));
+ self.checked_attrs.insert(attr.id);
+ self.assert_clean(item_span, self.dep_node(attr, def_id));
}
}
}
}
+}
+
+impl<'a, 'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'a, 'tcx> {
+ fn visit_item(&mut self, item: &'tcx hir::Item) {
+ self.check_item(item.id, item.span);
+ }
- fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+ fn visit_trait_item(&mut self, item: &hir::TraitItem) {
+ self.check_item(item.id, item.span);
}
- fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+ fn visit_impl_item(&mut self, item: &hir::ImplItem) {
+ self.check_item(item.id, item.span);
}
}
tcx.dep_graph.with_ignore(||{
let krate = tcx.hir.krate();
- krate.visit_all_item_likes(&mut DirtyCleanMetadataVisitor {
+ let mut dirty_clean_visitor = DirtyCleanMetadataVisitor {
tcx: tcx,
prev_metadata_hashes: prev_metadata_hashes,
current_metadata_hashes: current_metadata_hashes,
- });
+ checked_attrs: FxHashSet(),
+ };
+ krate.visit_all_item_likes(&mut dirty_clean_visitor);
+
+ let mut all_attrs = FindAllAttrs {
+ tcx: tcx,
+ attr_names: vec![ATTR_DIRTY_METADATA, ATTR_CLEAN_METADATA],
+ found_attrs: vec![],
+ };
+ intravisit::walk_crate(&mut all_attrs, krate);
+
+ // Note that we cannot use the existing "unused attribute"-infrastructure
+ // here, since that is running before trans. This is also the reason why
+ // all trans-specific attributes are `Whitelisted` in syntax::feature_gate.
+ all_attrs.report_unchecked_attrs(&dirty_clean_visitor.checked_attrs);
});
}
tcx: TyCtxt<'a, 'tcx, 'tcx>,
prev_metadata_hashes: &'m FxHashMap<DefId, Fingerprint>,
current_metadata_hashes: &'m FxHashMap<DefId, Fingerprint>,
+ checked_attrs: FxHashSet<ast::AttrId>,
}
impl<'a, 'tcx, 'm> ItemLikeVisitor<'tcx> for DirtyCleanMetadataVisitor<'a, 'tcx, 'm> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
- let def_id = self.tcx.hir.local_def_id(item.id);
+ self.check_item(item.id, item.span);
+ }
+
+ fn visit_trait_item(&mut self, item: &hir::TraitItem) {
+ self.check_item(item.id, item.span);
+ }
+
+ fn visit_impl_item(&mut self, item: &hir::ImplItem) {
+ self.check_item(item.id, item.span);
+ }
+}
+
+impl<'a, 'tcx, 'm> DirtyCleanMetadataVisitor<'a, 'tcx, 'm> {
+
+ fn check_item(&mut self, item_id: ast::NodeId, item_span: Span) {
+ let def_id = self.tcx.hir.local_def_id(item_id);
for attr in self.tcx.get_attrs(def_id).iter() {
if attr.check_name(ATTR_DIRTY_METADATA) {
if check_config(self.tcx, attr) {
- self.assert_state(false, def_id, item.span);
+ self.checked_attrs.insert(attr.id);
+ self.assert_state(false, def_id, item_span);
}
} else if attr.check_name(ATTR_CLEAN_METADATA) {
if check_config(self.tcx, attr) {
- self.assert_state(true, def_id, item.span);
+ self.checked_attrs.insert(attr.id);
+ self.assert_state(true, def_id, item_span);
}
}
}
}
- fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
- }
-
- fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
- }
-}
-
-impl<'a, 'tcx, 'm> DirtyCleanMetadataVisitor<'a, 'tcx, 'm> {
-
fn assert_state(&self, should_be_clean: bool, def_id: DefId, span: Span) {
let item_path = self.tcx.item_path_str(def_id);
debug!("assert_state({})", item_path);
/// Given a `#[rustc_dirty]` or `#[rustc_clean]` attribute, scan
/// for a `cfg="foo"` attribute and check whether we have a cfg
/// flag called `foo`.
-fn check_config(tcx: TyCtxt, attr: &ast::Attribute) -> bool {
+fn check_config(tcx: TyCtxt, attr: &Attribute) -> bool {
debug!("check_config(attr={:?})", attr);
let config = &tcx.sess.parse_sess.config;
debug!("check_config: config={:?}", config);
tcx.sess.span_fatal(item.span, &msg);
}
}
+
+
+// A visitor that collects all #[rustc_dirty]/#[rustc_clean] attributes from
+// the HIR. It is used to verfiy that we really ran checks for all annotated
+// nodes.
+pub struct FindAllAttrs<'a, 'tcx:'a> {
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ attr_names: Vec<&'static str>,
+ found_attrs: Vec<&'tcx Attribute>,
+}
+
+impl<'a, 'tcx> FindAllAttrs<'a, 'tcx> {
+
+ fn is_active_attr(&mut self, attr: &Attribute) -> bool {
+ for attr_name in &self.attr_names {
+ if attr.check_name(attr_name) && check_config(self.tcx, attr) {
+ return true;
+ }
+ }
+
+ false
+ }
+
+ fn report_unchecked_attrs(&self, checked_attrs: &FxHashSet<ast::AttrId>) {
+ for attr in &self.found_attrs {
+ if !checked_attrs.contains(&attr.id) {
+ self.tcx.sess.span_err(attr.span, &format!("found unchecked \
+ #[rustc_dirty]/#[rustc_clean] attribute"));
+ }
+ }
+ }
+}
+
+impl<'a, 'tcx> intravisit::Visitor<'tcx> for FindAllAttrs<'a, 'tcx> {
+ fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
+ intravisit::NestedVisitorMap::All(&self.tcx.hir)
+ }
+
+ fn visit_attribute(&mut self, attr: &'tcx Attribute) {
+ if self.is_active_attr(attr) {
+ self.found_attrs.push(attr);
+ }
+ }
+}
//! Code to save/load the dep-graph from files.
-use rustc::dep_graph::DepNode;
+use rustc::dep_graph::{DepNode, WorkProductId};
use rustc::hir::def_id::DefId;
use rustc::hir::svh::Svh;
use rustc::session::Session;
use rustc_serialize::Decodable as RustcDecodable;
use rustc_serialize::opaque::Decoder;
use std::path::{Path};
+use std::sync::Arc;
use IncrementalHashesMap;
use ich::Fingerprint;
use super::file_format;
use super::work_product;
-pub type DirtyNodes = FxHashSet<DepNode<DefPathIndex>>;
+// The key is a dirty node. The value is **some** base-input that we
+// can blame it on.
+pub type DirtyNodes = FxHashMap<DepNode<DefPathIndex>, DepNode<DefPathIndex>>;
/// If we are in incremental mode, and a previous dep-graph exists,
/// then load up those nodes/edges that are still valid into the
let directory = DefIdDirectory::decode(&mut dep_graph_decoder)?;
let serialized_dep_graph = SerializedDepGraph::decode(&mut dep_graph_decoder)?;
+ let edge_map: FxHashMap<_, _> = serialized_dep_graph.edges
+ .into_iter()
+ .map(|s| (s.source, s.targets))
+ .collect();
+
// Retrace the paths in the directory to find their current location (if any).
let retraced = directory.retrace(tcx);
- // Compute the set of Hir nodes whose data has changed or which
- // have been removed. These are "raw" source nodes, which means
- // that they still use the original `DefPathIndex` values from the
- // encoding, rather than having been retraced to a `DefId`. The
- // reason for this is that this way we can include nodes that have
- // been removed (which no longer have a `DefId` in the current
- // compilation).
- let dirty_raw_source_nodes = dirty_nodes(tcx,
- incremental_hashes_map,
- &serialized_dep_graph.hashes,
- &retraced);
-
- // Create a list of (raw-source-node ->
- // retracted-target-node) edges. In the process of retracing the
- // target nodes, we may discover some of them def-paths no longer exist,
- // in which case there is no need to mark the corresopnding nodes as dirty
- // (they are just not present). So this list may be smaller than the original.
- //
- // Note though that in the common case the target nodes are
- // `DepNode::WorkProduct` instances, and those don't have a
- // def-id, so they will never be considered to not exist. Instead,
- // we do a secondary hashing step (later, in trans) when we know
- // the set of symbols that go into a work-product: if any symbols
- // have been removed (or added) the hash will be different and
- // we'll ignore the work-product then.
- let retraced_edges: Vec<_> =
- serialized_dep_graph.edges.iter()
- .filter_map(|&(ref raw_source_node, ref raw_target_node)| {
- retraced.map(raw_target_node)
- .map(|target_node| (raw_source_node, target_node))
- })
- .collect();
-
- // Compute which work-products have an input that has changed or
- // been removed. Put the dirty ones into a set.
- let mut dirty_target_nodes = FxHashSet();
- for &(raw_source_node, ref target_node) in &retraced_edges {
- if dirty_raw_source_nodes.contains(raw_source_node) {
- if !dirty_target_nodes.contains(target_node) {
- dirty_target_nodes.insert(target_node.clone());
-
- if tcx.sess.opts.debugging_opts.incremental_info {
- // It'd be nice to pretty-print these paths better than just
- // using the `Debug` impls, but wev.
- println!("incremental: module {:?} is dirty because {:?} \
- changed or was removed",
- target_node,
- raw_source_node.map_def(|&index| {
- Some(directory.def_path_string(tcx, index))
- }).unwrap());
+ // Compute the set of nodes from the old graph where some input
+ // has changed or been removed. These are "raw" source nodes,
+ // which means that they still use the original `DefPathIndex`
+ // values from the encoding, rather than having been retraced to a
+ // `DefId`. The reason for this is that this way we can include
+ // nodes that have been removed (which no longer have a `DefId` in
+ // the current compilation).
+ let dirty_raw_nodes = initial_dirty_nodes(tcx,
+ incremental_hashes_map,
+ &serialized_dep_graph.hashes,
+ &retraced);
+ let dirty_raw_nodes = transitive_dirty_nodes(&edge_map, dirty_raw_nodes);
+
+ // Recreate the edges in the graph that are still clean.
+ let mut clean_work_products = FxHashSet();
+ let mut dirty_work_products = FxHashSet(); // incomplete; just used to suppress debug output
+ for (source, targets) in &edge_map {
+ for target in targets {
+ // If the target is dirty, skip the edge. If this is an edge
+ // that targets a work-product, we can print the blame
+ // information now.
+ if let Some(blame) = dirty_raw_nodes.get(target) {
+ if let DepNode::WorkProduct(ref wp) = *target {
+ if tcx.sess.opts.debugging_opts.incremental_info {
+ if dirty_work_products.insert(wp.clone()) {
+ // It'd be nice to pretty-print these paths better than just
+ // using the `Debug` impls, but wev.
+ println!("incremental: module {:?} is dirty because {:?} \
+ changed or was removed",
+ wp,
+ blame.map_def(|&index| {
+ Some(directory.def_path_string(tcx, index))
+ }).unwrap());
+ }
+ }
}
+ continue;
}
- }
- }
- // For work-products that are still clean, add their deps into the
- // graph. This is needed because later we will have to save this
- // back out again!
- let dep_graph = tcx.dep_graph.clone();
- for (raw_source_node, target_node) in retraced_edges {
- if dirty_target_nodes.contains(&target_node) {
- continue;
+ // If the source is dirty, the target will be dirty.
+ assert!(!dirty_raw_nodes.contains_key(source));
+
+ // Retrace the source -> target edges to def-ids and then
+ // create an edge in the graph. Retracing may yield none if
+ // some of the data happens to have been removed; this ought
+ // to be impossible unless it is dirty, so we can unwrap.
+ let source_node = retraced.map(source).unwrap();
+ let target_node = retraced.map(target).unwrap();
+ let _task = tcx.dep_graph.in_task(target_node);
+ tcx.dep_graph.read(source_node);
+ if let DepNode::WorkProduct(ref wp) = *target {
+ clean_work_products.insert(wp.clone());
+ }
}
-
- let source_node = retraced.map(raw_source_node).unwrap();
-
- debug!("decode_dep_graph: clean edge: {:?} -> {:?}", source_node, target_node);
-
- let _task = dep_graph.in_task(target_node);
- dep_graph.read(source_node);
}
// Add in work-products that are still clean, and delete those that are
// dirty.
- reconcile_work_products(tcx, work_products, &dirty_target_nodes);
+ reconcile_work_products(tcx, work_products, &clean_work_products);
- dirty_clean::check_dirty_clean_annotations(tcx, &dirty_raw_source_nodes, &retraced);
+ dirty_clean::check_dirty_clean_annotations(tcx, &dirty_raw_nodes, &retraced);
load_prev_metadata_hashes(tcx,
&retraced,
/// Computes which of the original set of def-ids are dirty. Stored in
/// a bit vector where the index is the DefPathIndex.
-fn dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- incremental_hashes_map: &IncrementalHashesMap,
- serialized_hashes: &[SerializedHash],
- retraced: &RetracedDefIdDirectory)
- -> DirtyNodes {
+fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ incremental_hashes_map: &IncrementalHashesMap,
+ serialized_hashes: &[SerializedHash],
+ retraced: &RetracedDefIdDirectory)
+ -> DirtyNodes {
let mut hcx = HashContext::new(tcx, incremental_hashes_map);
- let mut dirty_nodes = FxHashSet();
+ let mut dirty_nodes = FxHashMap();
for hash in serialized_hashes {
if let Some(dep_node) = retraced.map(&hash.dep_node) {
hash.dep_node);
}
- dirty_nodes.insert(hash.dep_node.clone());
+ dirty_nodes.insert(hash.dep_node.clone(), hash.dep_node.clone());
}
dirty_nodes
}
+fn transitive_dirty_nodes(edge_map: &FxHashMap<DepNode<DefPathIndex>, Vec<DepNode<DefPathIndex>>>,
+ mut dirty_nodes: DirtyNodes)
+ -> DirtyNodes
+{
+ let mut stack: Vec<(DepNode<DefPathIndex>, DepNode<DefPathIndex>)> = vec![];
+ stack.extend(dirty_nodes.iter().map(|(s, b)| (s.clone(), b.clone())));
+ while let Some((source, blame)) = stack.pop() {
+ // we know the source is dirty (because of the node `blame`)...
+ assert!(dirty_nodes.contains_key(&source));
+
+ // ...so we dirty all the targets (with the same blame)
+ if let Some(targets) = edge_map.get(&source) {
+ for target in targets {
+ if !dirty_nodes.contains_key(target) {
+ dirty_nodes.insert(target.clone(), blame.clone());
+ stack.push((target.clone(), blame.clone()));
+ }
+ }
+ }
+ }
+ dirty_nodes
+}
+
/// Go through the list of work-products produced in the previous run.
/// Delete any whose nodes have been found to be dirty or which are
/// otherwise no longer applicable.
fn reconcile_work_products<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
work_products: Vec<SerializedWorkProduct>,
- dirty_target_nodes: &FxHashSet<DepNode<DefId>>) {
+ clean_work_products: &FxHashSet<Arc<WorkProductId>>) {
debug!("reconcile_work_products({:?})", work_products);
for swp in work_products {
- if dirty_target_nodes.contains(&DepNode::WorkProduct(swp.id.clone())) {
+ if !clean_work_products.contains(&swp.id) {
debug!("reconcile_work_products: dep-node for {:?} is dirty", swp);
delete_dirty_work_product(tcx, swp);
} else {
+++ /dev/null
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use rustc::dep_graph::{DepGraphQuery, DepNode};
-use rustc::hir::def_id::DefId;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::bitvec::BitVector;
-use rustc_data_structures::graph::{NodeIndex, Graph};
-
-use super::hash::*;
-use ich::Fingerprint;
-
-/// A data-structure that makes it easy to enumerate the hashable
-/// predecessors of any given dep-node.
-pub struct Predecessors<'query> {
- // - Keys: dep-nodes that may have work-products, output meta-data
- // nodes.
- // - Values: transitive predecessors of the key that are hashable
- // (e.g., HIR nodes, input meta-data nodes)
- pub inputs: FxHashMap<&'query DepNode<DefId>, Vec<&'query DepNode<DefId>>>,
-
- // - Keys: some hashable node
- // - Values: the hash thereof
- pub hashes: FxHashMap<&'query DepNode<DefId>, Fingerprint>,
-}
-
-impl<'q> Predecessors<'q> {
- pub fn new(query: &'q DepGraphQuery<DefId>, hcx: &mut HashContext) -> Self {
- let tcx = hcx.tcx;
-
- let collect_for_metadata = tcx.sess.opts.debugging_opts.incremental_cc ||
- tcx.sess.opts.debugging_opts.query_dep_graph;
-
- // Find nodes for which we want to know the full set of preds
- let node_count = query.graph.len_nodes();
-
- // Set up some data structures the cache predecessor search needs:
- let mut visit_counts: Vec<u32> = Vec::new();
- let mut node_cache: Vec<Option<Box<[u32]>>> = Vec::new();
- visit_counts.resize(node_count, 0);
- node_cache.resize(node_count, None);
- let mut dfs_workspace1 = DfsWorkspace::new(node_count);
- let mut dfs_workspace2 = DfsWorkspace::new(node_count);
-
- let inputs: FxHashMap<_, _> = query
- .graph
- .all_nodes()
- .iter()
- .enumerate()
- .filter(|&(_, node)| match node.data {
- DepNode::WorkProduct(_) => true,
- DepNode::MetaData(ref def_id) => collect_for_metadata && def_id.is_local(),
-
- // if -Z query-dep-graph is passed, save more extended data
- // to enable better unit testing
- DepNode::TypeckTables(_) |
- DepNode::TransCrateItem(_) => tcx.sess.opts.debugging_opts.query_dep_graph,
-
- _ => false,
- })
- .map(|(node_index, node)| {
- find_roots(&query.graph,
- node_index as u32,
- &mut visit_counts,
- &mut node_cache[..],
- HashContext::is_hashable,
- &mut dfs_workspace1,
- Some(&mut dfs_workspace2));
-
- let inputs: Vec<_> = dfs_workspace1.output.nodes.iter().map(|&i| {
- query.graph.node_data(NodeIndex(i as usize))
- }).collect();
-
- (&node.data, inputs)
- })
- .collect();
-
- let mut hashes = FxHashMap();
- for input in inputs.values().flat_map(|v| v.iter().cloned()) {
- hashes.entry(input)
- .or_insert_with(|| hcx.hash(input).unwrap());
- }
-
- Predecessors {
- inputs: inputs,
- hashes: hashes,
- }
- }
-}
-
-const CACHING_THRESHOLD: u32 = 60;
-
-// Starting at `start_node`, this function finds this node's "roots", that is,
-// anything that is hashable, in the dep-graph. It uses a simple depth-first
-// search to achieve that. However, since some sub-graphs are traversed over
-// and over again, the function also some caching built into it: Each time it
-// visits a node it increases a counter for that node. If a node has been
-// visited more often than CACHING_THRESHOLD, the function will allocate a
-// cache entry in the `cache` array. This cache entry contains a flat list of
-// all roots reachable from the given node. The next time the node is visited,
-// the search can just add the contents of this array to the output instead of
-// recursing further.
-//
-// The function takes two `DfsWorkspace` arguments. These contains some data
-// structures that would be expensive to re-allocate all the time, so they are
-// allocated once up-front. There are two of them because building a cache entry
-// requires a recursive invocation of this function. Two are enough though,
-// since function never recurses more than once.
-fn find_roots<T, F>(graph: &Graph<T, ()>,
- start_node: u32,
- visit_counts: &mut [u32],
- cache: &mut [Option<Box<[u32]>>],
- is_root: F,
- workspace: &mut DfsWorkspace,
- mut sub_workspace: Option<&mut DfsWorkspace>)
- where F: Copy + Fn(&T) -> bool,
- T: ::std::fmt::Debug,
-{
- workspace.visited.clear();
- workspace.output.clear();
- workspace.stack.clear();
- workspace.stack.push(start_node);
-
- loop {
- let node = match workspace.stack.pop() {
- Some(node) => node,
- None => return,
- };
-
- if !workspace.visited.insert(node as usize) {
- continue
- }
-
- if is_root(graph.node_data(NodeIndex(node as usize))) {
- // If this is a root, just add it to the output.
- workspace.output.insert(node);
- } else {
- if let Some(ref cached) = cache[node as usize] {
- for &n in &cached[..] {
- workspace.output.insert(n);
- }
- // No need to recurse further from this node
- continue
- }
-
- visit_counts[node as usize] += 1;
-
- // If this node has been visited often enough to be cached ...
- if visit_counts[node as usize] > CACHING_THRESHOLD {
- // ... we are actually allowed to cache something, do so:
- if let Some(ref mut sub_workspace) = sub_workspace {
- // Note that the following recursive invocation does never
- // write to the cache (since we pass None as sub_workspace).
- // This is intentional: The graph we are working with
- // contains cycles and this prevent us from simply building
- // our caches recursively on-demand.
- // However, we can just do a regular, non-caching DFS to
- // yield the set of roots and cache that.
- find_roots(graph,
- node,
- visit_counts,
- cache,
- is_root,
- sub_workspace,
- None);
-
- for &n in &sub_workspace.output.nodes {
- workspace.output.insert(n);
- }
-
- cache[node as usize] = Some(sub_workspace.output
- .nodes
- .clone()
- .into_boxed_slice());
- // No need to recurse further from this node
- continue
- }
- }
-
- for pred in graph.predecessor_nodes(NodeIndex(node as usize)) {
- workspace.stack.push(pred.node_id() as u32);
- }
- }
- }
-}
-
-struct DfsWorkspace {
- stack: Vec<u32>,
- visited: BitVector,
- output: NodeIndexSet,
-}
-
-impl DfsWorkspace {
- fn new(total_node_count: usize) -> DfsWorkspace {
- DfsWorkspace {
- stack: Vec::new(),
- visited: BitVector::new(total_node_count),
- output: NodeIndexSet::new(total_node_count),
- }
- }
-}
-
-struct NodeIndexSet {
- bitset: BitVector,
- nodes: Vec<u32>,
-}
-
-impl NodeIndexSet {
- fn new(total_node_count: usize) -> NodeIndexSet {
- NodeIndexSet {
- bitset: BitVector::new(total_node_count),
- nodes: Vec::new(),
- }
- }
-
- #[inline]
- fn clear(&mut self) {
- self.bitset.clear();
- self.nodes.clear();
- }
-
- #[inline]
- fn insert(&mut self, node: u32) {
- if self.bitset.insert(node as usize) {
- self.nodes.push(node)
- }
- }
-}
-
-#[test]
-fn test_cached_dfs_acyclic() {
-
- // 0 1 2
- // | \ /
- // 3---+ |
- // | | |
- // | | |
- // 4 5 6
- // \ / \ / \
- // | | |
- // 7 8 9
-
- let mut g: Graph<bool, ()> = Graph::new();
- g.add_node(false);
- g.add_node(false);
- g.add_node(false);
- g.add_node(false);
- g.add_node(false);
- g.add_node(false);
- g.add_node(false);
- g.add_node(true);
- g.add_node(true);
- g.add_node(true);
-
- g.add_edge(NodeIndex(3), NodeIndex(0), ());
- g.add_edge(NodeIndex(4), NodeIndex(3), ());
- g.add_edge(NodeIndex(7), NodeIndex(4), ());
- g.add_edge(NodeIndex(5), NodeIndex(3), ());
- g.add_edge(NodeIndex(7), NodeIndex(5), ());
- g.add_edge(NodeIndex(8), NodeIndex(5), ());
- g.add_edge(NodeIndex(8), NodeIndex(6), ());
- g.add_edge(NodeIndex(9), NodeIndex(6), ());
- g.add_edge(NodeIndex(6), NodeIndex(1), ());
- g.add_edge(NodeIndex(6), NodeIndex(2), ());
-
- let mut ws1 = DfsWorkspace::new(g.len_nodes());
- let mut ws2 = DfsWorkspace::new(g.len_nodes());
- let mut visit_counts: Vec<_> = g.all_nodes().iter().map(|_| 0u32).collect();
- let mut cache: Vec<Option<Box<[u32]>>> = g.all_nodes().iter().map(|_| None).collect();
-
- fn is_root(x: &bool) -> bool { *x }
-
- for _ in 0 .. CACHING_THRESHOLD + 1 {
- find_roots(&g, 5, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2));
- ws1.output.nodes.sort();
- assert_eq!(ws1.output.nodes, vec![7, 8]);
-
- find_roots(&g, 6, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2));
- ws1.output.nodes.sort();
- assert_eq!(ws1.output.nodes, vec![8, 9]);
-
- find_roots(&g, 0, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2));
- ws1.output.nodes.sort();
- assert_eq!(ws1.output.nodes, vec![7, 8]);
-
- find_roots(&g, 1, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2));
- ws1.output.nodes.sort();
- assert_eq!(ws1.output.nodes, vec![8, 9]);
-
- find_roots(&g, 2, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2));
- ws1.output.nodes.sort();
- assert_eq!(ws1.output.nodes, vec![8, 9]);
-
- find_roots(&g, 3, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2));
- ws1.output.nodes.sort();
- assert_eq!(ws1.output.nodes, vec![7, 8]);
-
- find_roots(&g, 4, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2));
- ws1.output.nodes.sort();
- assert_eq!(ws1.output.nodes, vec![7]);
- }
-}
-
-#[test]
-fn test_cached_dfs_cyclic() {
-
- // 0 1 <---- 2 3
- // ^ | ^ ^
- // | v | |
- // 4 ----> 5 ----> 6 ----> 7
- // ^ ^ ^ ^
- // | | | |
- // 8 9 10 11
-
-
- let mut g: Graph<bool, ()> = Graph::new();
- g.add_node(false);
- g.add_node(false);
- g.add_node(false);
- g.add_node(false);
- g.add_node(false);
- g.add_node(false);
- g.add_node(false);
- g.add_node(false);
- g.add_node(true);
- g.add_node(true);
- g.add_node(true);
- g.add_node(true);
-
- g.add_edge(NodeIndex( 4), NodeIndex(0), ());
- g.add_edge(NodeIndex( 8), NodeIndex(4), ());
- g.add_edge(NodeIndex( 4), NodeIndex(5), ());
- g.add_edge(NodeIndex( 1), NodeIndex(5), ());
- g.add_edge(NodeIndex( 9), NodeIndex(5), ());
- g.add_edge(NodeIndex( 5), NodeIndex(6), ());
- g.add_edge(NodeIndex( 6), NodeIndex(2), ());
- g.add_edge(NodeIndex( 2), NodeIndex(1), ());
- g.add_edge(NodeIndex(10), NodeIndex(6), ());
- g.add_edge(NodeIndex( 6), NodeIndex(7), ());
- g.add_edge(NodeIndex(11), NodeIndex(7), ());
- g.add_edge(NodeIndex( 7), NodeIndex(3), ());
-
- let mut ws1 = DfsWorkspace::new(g.len_nodes());
- let mut ws2 = DfsWorkspace::new(g.len_nodes());
- let mut visit_counts: Vec<_> = g.all_nodes().iter().map(|_| 0u32).collect();
- let mut cache: Vec<Option<Box<[u32]>>> = g.all_nodes().iter().map(|_| None).collect();
-
- fn is_root(x: &bool) -> bool { *x }
-
- for _ in 0 .. CACHING_THRESHOLD + 1 {
- find_roots(&g, 2, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2));
- ws1.output.nodes.sort();
- assert_eq!(ws1.output.nodes, vec![8, 9, 10]);
-
- find_roots(&g, 3, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2));
- ws1.output.nodes.sort();
- assert_eq!(ws1.output.nodes, vec![8, 9, 10, 11]);
- }
-}
--- /dev/null
+Graph compression
+
+The graph compression algorithm is intended to remove and minimize the
+size of the dependency graph so it can be saved, while preserving
+everything we care about. In particular, given a set of input/output
+nodes in the graph (which must be disjoint), we ensure that the set of
+input nodes that can reach a given output node does not change,
+although the intermediate nodes may change in various ways. In short,
+the output nodes are intended to be the ones whose existence we care
+about when we start up, because they have some associated data that we
+will try to re-use (and hence if they are dirty, we have to throw that
+data away). The other intermediate nodes don't really matter so much.
+
+### Overview
+
+The algorithm works as follows:
+
+1. Do a single walk of the graph to construct a DAG
+ - in this walk, we identify and unify all cycles, electing a representative "head" node
+ - this is done using the union-find implementation
+ - this code is found in the `classify` module
+2. The result from this walk is a `Dag`:
+ - the set of SCCs, represented by the union-find table
+ - a set of edges in the new DAG, represented by:
+ - a vector of parent nodes for each child node
+ - a vector of cross-edges
+ - once these are canonicalized, some of these edges may turn out to be cyclic edges
+ (i.e., an edge A -> A where A is the head of some SCC)
+3. We pass this `Dag` into the construct code, which then creates a
+ new graph. This graph has a smaller set of indices which includes
+ *at least* the inputs/outputs from the original graph, but may have
+ other nodes as well, if keeping them reduces the overall size of
+ the graph.
+ - This code is found in the `construct` module.
+
+### Some notes
+
+The input graph is assumed to have *read-by* edges. i.e., `A -> B`
+means that the task B reads data from A. But the DAG defined by
+classify is expressed in terms of *reads-from* edges, which are the
+inverse. So `A -> B` is the same as `B -rf-> A`. *reads-from* edges
+are more natural since we want to walk from the outputs to the inputs,
+effectively. When we construct the final graph, we reverse these edges
+back into the *read-by* edges common elsewhere.
+
+
+
+
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! First phase. Detect cycles and cross-edges.
+
+use super::*;
+
+#[cfg(test)]
+mod test;
+
+pub struct Classify<'a, 'g: 'a, N: 'g, I: 'a, O: 'a>
+ where N: Debug + Clone + 'g,
+ I: Fn(&N) -> bool,
+ O: Fn(&N) -> bool,
+{
+ r: &'a mut GraphReduce<'g, N, I, O>,
+ stack: Vec<NodeIndex>,
+ colors: Vec<Color>,
+ dag: Dag,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+enum Color {
+ // not yet visited
+ White,
+
+ // visiting; usize is index on stack
+ Grey(usize),
+
+ // finished visiting
+ Black,
+}
+
+impl<'a, 'g, N, I, O> Classify<'a, 'g, N, I, O>
+ where N: Debug + Clone + 'g,
+ I: Fn(&N) -> bool,
+ O: Fn(&N) -> bool,
+{
+ pub(super) fn new(r: &'a mut GraphReduce<'g, N, I, O>) -> Self {
+ Classify {
+ r: r,
+ colors: vec![Color::White; r.in_graph.len_nodes()],
+ stack: vec![],
+ dag: Dag {
+ parents: (0..r.in_graph.len_nodes()).map(|i| NodeIndex(i)).collect(),
+ cross_edges: vec![],
+ input_nodes: vec![],
+ output_nodes: vec![],
+ },
+ }
+ }
+
+ pub(super) fn walk(mut self) -> Dag {
+ for (index, node) in self.r.in_graph.all_nodes().iter().enumerate() {
+ if (self.r.is_output)(&node.data) {
+ let index = NodeIndex(index);
+ self.dag.output_nodes.push(index);
+ match self.colors[index.0] {
+ Color::White => self.open(index),
+ Color::Grey(_) => panic!("grey node but have not yet started a walk"),
+ Color::Black => (), // already visited, skip
+ }
+ }
+ }
+
+ // At this point we've identifed all the cycles, and we've
+ // constructed a spanning tree over the original graph
+ // (encoded in `self.parents`) as well as a list of
+ // cross-edges that reflect additional edges from the DAG.
+ //
+ // If we converted each node to its `cycle-head` (a
+ // representative choice from each SCC, basically) and then
+ // take the union of `self.parents` and `self.cross_edges`
+ // (after canonicalization), that is basically our DAG.
+ //
+ // Note that both of those may well contain trivial `X -rf-> X`
+ // cycle edges after canonicalization, though. e.g., if you
+ // have a graph `{A -rf-> B, B -rf-> A}`, we will have unioned A and
+ // B, but A will also be B's parent (or vice versa), and hence
+ // when we canonicalize the parent edge it would become `A -rf->
+ // A` (or `B -rf-> B`).
+ self.dag
+ }
+
+ fn open(&mut self, node: NodeIndex) {
+ let index = self.stack.len();
+ self.stack.push(node);
+ self.colors[node.0] = Color::Grey(index);
+ for child in self.r.inputs(node) {
+ self.walk_edge(node, child);
+ }
+ self.stack.pop().unwrap();
+ self.colors[node.0] = Color::Black;
+
+ if (self.r.is_input)(&self.r.in_graph.node_data(node)) {
+ // base inputs should have no inputs
+ assert!(self.r.inputs(node).next().is_none());
+ debug!("input: `{:?}`", self.r.in_graph.node_data(node));
+ self.dag.input_nodes.push(node);
+ }
+ }
+
+ fn walk_edge(&mut self, parent: NodeIndex, child: NodeIndex) {
+ debug!("walk_edge: {:?} -rf-> {:?}, {:?}",
+ self.r.in_graph.node_data(parent),
+ self.r.in_graph.node_data(child),
+ self.colors[child.0]);
+
+ // Ignore self-edges, just in case they exist.
+ if child == parent {
+ return;
+ }
+
+ match self.colors[child.0] {
+ Color::White => {
+ // Not yet visited this node; start walking it.
+ assert_eq!(self.dag.parents[child.0], child);
+ self.dag.parents[child.0] = parent;
+ self.open(child);
+ }
+
+ Color::Grey(stack_index) => {
+ // Back-edge; unify everything on stack between here and `stack_index`
+ // since we are all participating in a cycle
+ assert!(self.stack[stack_index] == child);
+
+ for &n in &self.stack[stack_index..] {
+ debug!("cycle `{:?}` and `{:?}`",
+ self.r.in_graph.node_data(n),
+ self.r.in_graph.node_data(parent));
+ self.r.mark_cycle(n, parent);
+ }
+ }
+
+ Color::Black => {
+ // Cross-edge, record and ignore
+ self.dag.cross_edges.push((parent, child));
+ debug!("cross-edge `{:?} -rf-> {:?}`",
+ self.r.in_graph.node_data(parent),
+ self.r.in_graph.node_data(child));
+ }
+ }
+ }
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::*;
+
+#[test]
+fn detect_cycles() {
+ let (graph, nodes) = graph! {
+ A -> C0,
+ A -> C1,
+ B -> C1,
+ C0 -> C1,
+ C1 -> C0,
+ C0 -> D,
+ C1 -> E,
+ };
+ let inputs = ["A", "B"];
+ let outputs = ["D", "E"];
+ let mut reduce = GraphReduce::new(&graph, |n| inputs.contains(n), |n| outputs.contains(n));
+ Classify::new(&mut reduce).walk();
+
+ assert!(!reduce.in_cycle(nodes("A"), nodes("C0")));
+ assert!(!reduce.in_cycle(nodes("B"), nodes("C0")));
+ assert!(reduce.in_cycle(nodes("C0"), nodes("C1")));
+ assert!(!reduce.in_cycle(nodes("D"), nodes("C0")));
+ assert!(!reduce.in_cycle(nodes("E"), nodes("C0")));
+ assert!(!reduce.in_cycle(nodes("E"), nodes("A")));
+}
+
+/// Regr test for a bug where we forgot to pop nodes off of the stack
+/// as we were walking. In this case, because edges are pushed to the front
+/// of the list, we would visit OUT, then A, then IN, and then close IN (but forget
+/// to POP. Then visit B, C, and then A, which would mark everything from A to C as
+/// cycle. But since we failed to pop IN, the stack was `OUT, A, IN, B, C` so that
+/// marked C and IN as being in a cycle.
+#[test]
+fn edge_order1() {
+ let (graph, nodes) = graph! {
+ A -> C,
+ C -> B,
+ B -> A,
+ IN -> B,
+ IN -> A,
+ A -> OUT,
+ };
+ let inputs = ["IN"];
+ let outputs = ["OUT"];
+ let mut reduce = GraphReduce::new(&graph, |n| inputs.contains(n), |n| outputs.contains(n));
+ Classify::new(&mut reduce).walk();
+
+ // A, B, and C are mutually in a cycle, but IN/OUT are not participating.
+ let names = ["A", "B", "C", "IN", "OUT"];
+ let cycle_names = ["A", "B", "C"];
+ for &i in &names {
+ for &j in names.iter().filter(|&&j| j != i) {
+ let in_cycle = cycle_names.contains(&i) && cycle_names.contains(&j);
+ assert_eq!(reduce.in_cycle(nodes(i), nodes(j)), in_cycle,
+ "cycle status for nodes {} and {} is incorrect",
+ i, j);
+ }
+ }
+}
+
+/// Same as `edge_order1` but in reverse order so as to detect a failure
+/// if we were to enqueue edges onto end of list instead.
+#[test]
+fn edge_order2() {
+ let (graph, nodes) = graph! {
+ A -> OUT,
+ IN -> A,
+ IN -> B,
+ B -> A,
+ C -> B,
+ A -> C,
+ };
+ let inputs = ["IN"];
+ let outputs = ["OUT"];
+ let mut reduce = GraphReduce::new(&graph, |n| inputs.contains(n), |n| outputs.contains(n));
+ Classify::new(&mut reduce).walk();
+
+ assert!(reduce.in_cycle(nodes("B"), nodes("C")));
+
+ assert!(!reduce.in_cycle(nodes("IN"), nodes("A")));
+ assert!(!reduce.in_cycle(nodes("IN"), nodes("B")));
+ assert!(!reduce.in_cycle(nodes("IN"), nodes("C")));
+ assert!(!reduce.in_cycle(nodes("IN"), nodes("OUT")));
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Second phase. Construct new graph. The previous phase has
+//! converted the input graph into a DAG by detecting and unifying
+//! cycles. It provides us with the following (which is a
+//! representation of the DAG):
+//!
+//! - SCCs, in the form of a union-find repr that can convert each node to
+//! its *cycle head* (an arbitrarly chosen representative from the cycle)
+//! - a vector of *leaf nodes*, just a convenience
+//! - a vector of *parents* for each node (in some cases, nodes have no parents,
+//! or their parent is another member of same cycle; in that case, the vector
+//! will be stored `v[i] == i`, after canonicalization)
+//! - a vector of *cross edges*, meaning add'l edges between graphs nodes beyond
+//! the parents.
+
+use rustc_data_structures::fx::FxHashMap;
+
+use super::*;
+
+pub(super) fn construct_graph<'g, N, I, O>(r: &mut GraphReduce<'g, N, I, O>, dag: Dag)
+ -> Reduction<'g, N>
+ where N: Debug + Clone, I: Fn(&N) -> bool, O: Fn(&N) -> bool,
+{
+ let Dag { parents: old_parents, input_nodes, output_nodes, cross_edges } = dag;
+ let in_graph = r.in_graph;
+
+ debug!("construct_graph");
+
+ // Create a canonical list of edges; this includes both parent and
+ // cross-edges. We store this in `(target -> Vec<source>)` form.
+ // We call the first edge to any given target its "parent".
+ let mut edges = FxHashMap();
+ let old_parent_edges = old_parents.iter().cloned().zip((0..).map(NodeIndex));
+ for (source, target) in old_parent_edges.chain(cross_edges) {
+ debug!("original edge `{:?} -rf-> {:?}`",
+ in_graph.node_data(source),
+ in_graph.node_data(target));
+ let source = r.cycle_head(source);
+ let target = r.cycle_head(target);
+ if source != target {
+ let v = edges.entry(target).or_insert(vec![]);
+ if !v.contains(&source) {
+ debug!("edge `{:?} -rf-> {:?}` is edge #{} with that target",
+ in_graph.node_data(source),
+ in_graph.node_data(target),
+ v.len());
+ v.push(source);
+ }
+ }
+ }
+ let parent = |ni: NodeIndex| -> NodeIndex {
+ edges[&ni][0]
+ };
+
+ // `retain_map`: a map of those nodes that we will want to
+ // *retain* in the ultimate graph; the key is the node index in
+ // the old graph, the value is the node index in the new
+ // graph. These are nodes in the following categories:
+ //
+ // - inputs
+ // - work-products
+ // - targets of a cross-edge
+ //
+ // The first two categories hopefully make sense. We want the
+ // inputs so we can compare hashes later. We want the
+ // work-products so we can tell precisely when a given
+ // work-product is invalidated. But the last one isn't strictly
+ // needed; we keep cross-target edges so as to minimize the total
+ // graph size.
+ //
+ // Consider a graph like:
+ //
+ // WP0 -rf-> Y
+ // WP1 -rf-> Y
+ // Y -rf-> INPUT0
+ // Y -rf-> INPUT1
+ // Y -rf-> INPUT2
+ // Y -rf-> INPUT3
+ //
+ // Now if we were to remove Y, we would have a total of 8 edges: both WP0 and WP1
+ // depend on INPUT0...INPUT3. As it is, we have 6 edges.
+ //
+ // NB: The current rules are not optimal. For example, given this
+ // input graph:
+ //
+ // OUT0 -rf-> X
+ // OUT1 -rf-> X
+ // X -rf -> INPUT0
+ //
+ // we will preserve X because it has two "consumers" (OUT0 and
+ // OUT1). We could as easily skip it, but we'd have to tally up
+ // the number of input nodes that it (transitively) reaches, and I
+ // was too lazy to do so. This is the unit test `suboptimal`.
+
+ let mut retain_map = FxHashMap();
+ let mut new_graph = Graph::new();
+
+ {
+ // Start by adding start-nodes and inputs.
+ let retained_nodes = output_nodes.iter().chain(&input_nodes).map(|&n| r.cycle_head(n));
+
+ // Next add in targets of cross-edges. Due to the canonicalization,
+ // some of these may be self-edges or may may duplicate the parent
+ // edges, so ignore those.
+ let retained_nodes = retained_nodes.chain(
+ edges.iter()
+ .filter(|&(_, ref sources)| sources.len() > 1)
+ .map(|(&target, _)| target));
+
+ // Now create the new graph, adding in the entries from the map.
+ for n in retained_nodes {
+ retain_map.entry(n)
+ .or_insert_with(|| {
+ let data = in_graph.node_data(n);
+ debug!("retaining node `{:?}`", data);
+ new_graph.add_node(data)
+ });
+ }
+ }
+
+ // Given a cycle-head `ni`, converts it to the closest parent that has
+ // been retained in the output graph.
+ let retained_parent = |mut ni: NodeIndex| -> NodeIndex {
+ loop {
+ debug!("retained_parent({:?})", in_graph.node_data(ni));
+ match retain_map.get(&ni) {
+ Some(&v) => return v,
+ None => ni = parent(ni),
+ }
+ }
+ };
+
+ // Now add in the edges into the graph.
+ for (&target, sources) in &edges {
+ if let Some(&r_target) = retain_map.get(&target) {
+ debug!("adding edges that target `{:?}`", in_graph.node_data(target));
+ for &source in sources {
+ debug!("new edge `{:?} -rf-> {:?}`",
+ in_graph.node_data(source),
+ in_graph.node_data(target));
+ let r_source = retained_parent(source);
+
+ // NB. In the input graph, we have `a -> b` if b
+ // **reads from** a. But in the terminology of this
+ // code, we would describe that edge as `b -> a`,
+ // because we have edges *from* outputs *to* inputs.
+ // Therefore, when we create our new graph, we have to
+ // reverse the edge.
+ new_graph.add_edge(r_target, r_source, ());
+ }
+ } else {
+ assert_eq!(sources.len(), 1);
+ }
+ }
+
+ // One complication. In some cases, output nodes *may* participate in
+ // cycles. An example:
+ //
+ // [HIR0] [HIR1]
+ // | |
+ // v v
+ // TypeckClosureBody(X) -> ItemSignature(X::SomeClosureInX)
+ // | ^ | |
+ // | +-------------------------+ |
+ // | |
+ // v v
+ // Foo Bar
+ //
+ // In these cases, the output node may not wind up as the head
+ // of the cycle, in which case it would be absent from the
+ // final graph. We don't wish this to happen, therefore we go
+ // over the list of output nodes again and check for any that
+ // are not their own cycle-head. If we find such a node, we
+ // add it to the graph now with an edge from the cycle head.
+ // So the graph above could get transformed into this:
+ //
+ // [HIR0, HIR1]
+ // |
+ // v
+ // TypeckClosureBody(X) ItemSignature(X::SomeClosureInX)
+ // ^ | |
+ // +-------------------------+ |
+ // v
+ // [Foo, Bar]
+ //
+ // (Note that all the edges here are "read-by" edges, not
+ // "reads-from" edges.)
+ for &output_node in &output_nodes {
+ let head = r.cycle_head(output_node);
+ if output_node == head {
+ assert!(retain_map.contains_key(&output_node));
+ } else {
+ assert!(!retain_map.contains_key(&output_node));
+ let output_data = in_graph.node_data(output_node);
+ let new_node = new_graph.add_node(output_data);
+ let new_head_node = retain_map[&head];
+ new_graph.add_edge(new_head_node, new_node, ());
+ }
+ }
+
+ // Finally, prepare a list of the input node indices as found in
+ // the new graph. Note that since all input nodes are leaves in
+ // the graph, they should never participate in a cycle.
+ let input_nodes =
+ input_nodes.iter()
+ .map(|&n| {
+ assert_eq!(r.cycle_head(n), n, "input node participating in a cycle");
+ retain_map[&n]
+ })
+ .collect();
+
+ Reduction { graph: new_graph, input_nodes: input_nodes }
+}
+
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc_data_structures::graph::NodeIndex;
+use rustc_data_structures::unify::UnifyKey;
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct DagId {
+ index: u32,
+}
+
+impl DagId {
+ pub fn from_input_index(n: NodeIndex) -> Self {
+ DagId { index: n.0 as u32 }
+ }
+
+ pub fn as_input_index(&self) -> NodeIndex {
+ NodeIndex(self.index as usize)
+ }
+}
+
+impl UnifyKey for DagId {
+ type Value = ();
+
+ fn index(&self) -> u32 {
+ self.index
+ }
+
+ fn from_index(u: u32) -> Self {
+ DagId { index: u }
+ }
+
+ fn tag(_: Option<Self>) -> &'static str {
+ "DagId"
+ }
+}
--- /dev/null
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Graph compression. See `README.md`.
+
+use rustc_data_structures::graph::{Graph, NodeIndex};
+use rustc_data_structures::unify::UnificationTable;
+use std::fmt::Debug;
+
+#[cfg(test)]
+#[macro_use]
+mod test_macro;
+
+mod construct;
+
+mod classify;
+use self::classify::Classify;
+
+mod dag_id;
+use self::dag_id::DagId;
+
+#[cfg(test)]
+mod test;
+
+pub fn reduce_graph<N, I, O>(graph: &Graph<N, ()>,
+ is_input: I,
+ is_output: O) -> Reduction<N>
+ where N: Debug + Clone,
+ I: Fn(&N) -> bool,
+ O: Fn(&N) -> bool,
+{
+ GraphReduce::new(graph, is_input, is_output).compute()
+}
+
+pub struct Reduction<'q, N> where N: 'q + Debug + Clone {
+ pub graph: Graph<&'q N, ()>,
+ pub input_nodes: Vec<NodeIndex>,
+}
+
+struct GraphReduce<'q, N, I, O>
+ where N: 'q + Debug + Clone,
+ I: Fn(&N) -> bool,
+ O: Fn(&N) -> bool,
+{
+ in_graph: &'q Graph<N, ()>,
+ unify: UnificationTable<DagId>,
+ is_input: I,
+ is_output: O,
+}
+
+struct Dag {
+ // The "parent" of a node is the node which reached it during the
+ // initial DFS. To encode the case of "no parent" (i.e., for the
+ // roots of the walk), we make `parents[i] == i` to start, which
+ // turns out be convenient.
+ parents: Vec<NodeIndex>,
+
+ // Additional edges beyond the parents.
+ cross_edges: Vec<(NodeIndex, NodeIndex)>,
+
+ // Nodes which we found that are considered "outputs"
+ output_nodes: Vec<NodeIndex>,
+
+ // Nodes which we found that are considered "inputs"
+ input_nodes: Vec<NodeIndex>,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+struct DagNode {
+ in_index: NodeIndex
+}
+
+impl<'q, N, I, O> GraphReduce<'q, N, I, O>
+ where N: Debug + Clone,
+ I: Fn(&N) -> bool,
+ O: Fn(&N) -> bool,
+{
+ fn new(in_graph: &'q Graph<N, ()>, is_input: I, is_output: O) -> Self {
+ let mut unify = UnificationTable::new();
+
+ // create a set of unification keys whose indices
+ // correspond to the indices from the input graph
+ for i in 0..in_graph.len_nodes() {
+ let k = unify.new_key(());
+ assert!(k == DagId::from_input_index(NodeIndex(i)));
+ }
+
+ GraphReduce { in_graph, unify, is_input, is_output }
+ }
+
+ fn compute(mut self) -> Reduction<'q, N> {
+ let dag = Classify::new(&mut self).walk();
+ construct::construct_graph(&mut self, dag)
+ }
+
+ fn inputs(&self, in_node: NodeIndex) -> impl Iterator<Item = NodeIndex> + 'q {
+ self.in_graph.predecessor_nodes(in_node)
+ }
+
+ fn mark_cycle(&mut self, in_node1: NodeIndex, in_node2: NodeIndex) {
+ let dag_id1 = DagId::from_input_index(in_node1);
+ let dag_id2 = DagId::from_input_index(in_node2);
+ self.unify.union(dag_id1, dag_id2);
+ }
+
+ /// Convert a dag-id into its cycle head representative. This will
+ /// be a no-op unless `in_node` participates in a cycle, in which
+ /// case a distinct node *may* be returned.
+ fn cycle_head(&mut self, in_node: NodeIndex) -> NodeIndex {
+ let i = DagId::from_input_index(in_node);
+ self.unify.find(i).as_input_index()
+ }
+
+ #[cfg(test)]
+ fn in_cycle(&mut self, ni1: NodeIndex, ni2: NodeIndex) -> bool {
+ self.cycle_head(ni1) == self.cycle_head(ni2)
+ }
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::*;
+
+fn reduce(graph: &Graph<&'static str, ()>,
+ inputs: &[&'static str],
+ outputs: &[&'static str],
+ expected: &[&'static str])
+{
+ let reduce = GraphReduce::new(&graph,
+ |n| inputs.contains(n),
+ |n| outputs.contains(n));
+ let result = reduce.compute();
+ let mut edges: Vec<String> =
+ result.graph
+ .all_edges()
+ .iter()
+ .map(|edge| format!("{} -> {}",
+ result.graph.node_data(edge.source()),
+ result.graph.node_data(edge.target())))
+ .collect();
+ edges.sort();
+ println!("{:#?}", edges);
+ assert_eq!(edges.len(), expected.len());
+ for (expected, actual) in expected.iter().zip(&edges) {
+ assert_eq!(expected, actual);
+ }
+}
+
+#[test]
+fn test1() {
+ // +---------------+
+ // | |
+ // | +--------|------+
+ // | | v v
+ // [A] -> [C0] -> [C1] [D]
+ // [ ] <- [ ] -> [E]
+ // ^
+ // [B] -------------+
+ let (graph, _nodes) = graph! {
+ A -> C0,
+ A -> C1,
+ B -> C1,
+ C0 -> C1,
+ C1 -> C0,
+ C0 -> D,
+ C1 -> E,
+ };
+
+ // [A] -> [C1] -> [D]
+ // [B] -> [ ] -> [E]
+ reduce(&graph, &["A", "B"], &["D", "E"], &[
+ "A -> C1",
+ "B -> C1",
+ "C1 -> D",
+ "C1 -> E",
+ ]);
+}
+
+#[test]
+fn test2() {
+ // +---------------+
+ // | |
+ // | +--------|------+
+ // | | v v
+ // [A] -> [C0] -> [C1] [D] -> [E]
+ // [ ] <- [ ]
+ // ^
+ // [B] -------------+
+ let (graph, _nodes) = graph! {
+ A -> C0,
+ A -> C1,
+ B -> C1,
+ C0 -> C1,
+ C1 -> C0,
+ C0 -> D,
+ D -> E,
+ };
+
+ // [A] -> [D] -> [E]
+ // [B] -> [ ]
+ reduce(&graph, &["A", "B"], &["D", "E"], &[
+ "A -> D",
+ "B -> D",
+ "D -> E",
+ ]);
+}
+
+#[test]
+fn test2b() {
+ // Variant on test2 in which [B] is not
+ // considered an input.
+ let (graph, _nodes) = graph! {
+ A -> C0,
+ A -> C1,
+ B -> C1,
+ C0 -> C1,
+ C1 -> C0,
+ C0 -> D,
+ D -> E,
+ };
+
+ // [A] -> [D] -> [E]
+ reduce(&graph, &["A"], &["D", "E"], &[
+ "A -> D",
+ "D -> E",
+ ]);
+}
+
+#[test]
+fn test3() {
+
+ // Edges going *downwards*, so 0, 1 and 2 are inputs,
+ // while 7, 8, and 9 are outputs.
+ //
+ // 0 1 2
+ // | \ /
+ // 3---+ |
+ // | | |
+ // | | |
+ // 4 5 6
+ // \ / \ / \
+ // | | |
+ // 7 8 9
+ //
+ // Here the end result removes node 4, instead encoding an edge
+ // from n3 -> n7, but keeps nodes 5 and 6, as they are common
+ // inputs to nodes 8/9.
+
+ let (graph, _nodes) = graph! {
+ n0 -> n3,
+ n3 -> n4,
+ n3 -> n5,
+ n4 -> n7,
+ n5 -> n7,
+ n5 -> n8,
+ n1 -> n6,
+ n2 -> n6,
+ n6 -> n8,
+ n6 -> n9,
+ };
+
+ reduce(&graph, &["n0", "n1", "n2"], &["n7", "n8", "n9"], &[
+ "n0 -> n3",
+ "n1 -> n6",
+ "n2 -> n6",
+ "n3 -> n5",
+ "n3 -> n7",
+ "n5 -> n7",
+ "n5 -> n8",
+ "n6 -> n8",
+ "n6 -> n9"
+ ]);
+}
+
+#[test]
+fn test_cached_dfs_cyclic() {
+
+ // 0 1 <---- 2 3
+ // ^ | ^ ^
+ // | v | |
+ // 4 ----> 5 ----> 6 ----> 7
+ // ^ ^ ^ ^
+ // | | | |
+ // 8 9 10 11
+
+ let (graph, _nodes) = graph! {
+ // edges from above diagram, in columns, top-to-bottom:
+ n4 -> n0,
+ n8 -> n4,
+ n4 -> n5,
+ n1 -> n5,
+ n9 -> n5,
+ n2 -> n1,
+ n5 -> n6,
+ n6 -> n2,
+ n10 -> n6,
+ n6 -> n7,
+ n7 -> n3,
+ n11 -> n7,
+ };
+
+ // 0 1 2 3
+ // ^ ^ / ^
+ // | |/ |
+ // 4 ----> 5 --------------+
+ // ^ ^ \ |
+ // | | \ |
+ // 8 9 10 11
+
+ reduce(&graph, &["n8", "n9", "n10", "n11"], &["n0", "n1", "n2", "n3"], &[
+ "n10 -> n5",
+ "n11 -> n3",
+ "n4 -> n0",
+ "n4 -> n5",
+ "n5 -> n1",
+ "n5 -> n2",
+ "n5 -> n3",
+ "n8 -> n4",
+ "n9 -> n5"
+ ]);
+}
+
+/// Demonstrates the case where we don't reduce as much as we could.
+#[test]
+fn suboptimal() {
+ let (graph, _nodes) = graph! {
+ INPUT0 -> X,
+ X -> OUTPUT0,
+ X -> OUTPUT1,
+ };
+
+ reduce(&graph, &["INPUT0"], &["OUTPUT0", "OUTPUT1"], &[
+ "INPUT0 -> X",
+ "X -> OUTPUT0",
+ "X -> OUTPUT1"
+ ]);
+}
+
+#[test]
+fn test_cycle_output() {
+ // +---------------+
+ // | |
+ // | +--------|------+
+ // | | v v
+ // [A] -> [C0] <-> [C1] <- [D]
+ // +----> [E]
+ // ^
+ // [B] ----------------- ---+
+ let (graph, _nodes) = graph! {
+ A -> C0,
+ A -> C1,
+ B -> E,
+ C0 -> C1,
+ C1 -> C0,
+ C0 -> D,
+ C1 -> E,
+ D -> C1,
+ };
+
+ // [A] -> [C0] --> [D]
+ // +----> [E]
+ // ^
+ // [B] -------------+
+ reduce(&graph, &["A", "B"], &["D", "E"], &[
+ "A -> C0",
+ "B -> E",
+ "C0 -> D",
+ "C0 -> E",
+ ]);
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! graph {
+ ($( $source:ident -> $target:ident, )*) => {
+ {
+ use $crate::rustc_data_structures::graph::{Graph, NodeIndex};
+ use $crate::rustc_data_structures::fx::FxHashMap;
+
+ let mut graph = Graph::new();
+ let mut nodes: FxHashMap<&'static str, NodeIndex> = FxHashMap();
+
+ for &name in &[ $(stringify!($source), stringify!($target)),* ] {
+ let name: &'static str = name;
+ nodes.entry(name)
+ .or_insert_with(|| graph.add_node(name));
+ }
+
+ $(
+ {
+ let source = nodes[&stringify!($source)];
+ let target = nodes[&stringify!($target)];
+ graph.add_edge(source, target, ());
+ }
+ )*
+
+ let f = move |name: &'static str| -> NodeIndex { nodes[&name] };
+
+ (graph, f)
+ }
+ }
+}
+
+macro_rules! set {
+ ($( $value:expr ),*) => {
+ {
+ use $crate::rustc_data_structures::fx::FxHashSet;
+ let mut set = FxHashSet();
+ $(set.insert($value);)*
+ set
+ }
+ }
+}
--- /dev/null
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::dep_graph::{DepGraphQuery, DepNode};
+use rustc::hir::def_id::DefId;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::graph::Graph;
+
+use super::hash::*;
+use ich::Fingerprint;
+
+mod compress;
+
+/// A data-structure that makes it easy to enumerate the hashable
+/// predecessors of any given dep-node.
+pub struct Predecessors<'query> {
+ // A reduced version of the input graph that contains fewer nodes.
+ // This is intended to keep all of the base inputs (i.e., HIR
+ // nodes) and all of the "work-products" we may care about
+ // later. Other nodes may be retained if it keeps the overall size
+ // of the graph down.
+ pub reduced_graph: Graph<&'query DepNode<DefId>, ()>,
+
+ // For the inputs (hir/foreign-metadata), we include hashes.
+ pub hashes: FxHashMap<&'query DepNode<DefId>, Fingerprint>,
+}
+
+impl<'q> Predecessors<'q> {
+ pub fn new(query: &'q DepGraphQuery<DefId>, hcx: &mut HashContext) -> Self {
+ let tcx = hcx.tcx;
+
+ let collect_for_metadata = tcx.sess.opts.debugging_opts.incremental_cc ||
+ tcx.sess.opts.debugging_opts.query_dep_graph;
+
+ // Find the set of "start nodes". These are nodes that we will
+ // possibly query later.
+ let is_output = |node: &DepNode<DefId>| -> bool {
+ match *node {
+ DepNode::WorkProduct(_) => true,
+ DepNode::MetaData(ref def_id) => collect_for_metadata && def_id.is_local(),
+
+ // if -Z query-dep-graph is passed, save more extended data
+ // to enable better unit testing
+ DepNode::TypeckTables(_) |
+ DepNode::TransCrateItem(_) => tcx.sess.opts.debugging_opts.query_dep_graph,
+
+ _ => false,
+ }
+ };
+
+ // Reduce the graph to the most important nodes.
+ let compress::Reduction { graph, input_nodes } =
+ compress::reduce_graph(&query.graph, HashContext::is_hashable, is_output);
+
+ let mut hashes = FxHashMap();
+ for input_index in input_nodes {
+ let input = *graph.node_data(input_index);
+ debug!("computing hash for input node `{:?}`", input);
+ hashes.entry(input)
+ .or_insert_with(|| hcx.hash(input).unwrap());
+ }
+
+ Predecessors {
+ reduced_graph: graph,
+ hashes: hashes,
+ }
+ }
+}
use rustc::session::Session;
use rustc::ty::TyCtxt;
use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::graph::{NodeIndex, INCOMING};
use rustc_serialize::Encodable as RustcEncodable;
use rustc_serialize::opaque::Encoder;
use std::hash::Hash;
// Create a flat list of (Input, WorkProduct) edges for
// serialization.
- let mut edges = vec![];
- for (&target, sources) in &preds.inputs {
+ let mut edges = FxHashMap();
+ for edge in preds.reduced_graph.all_edges() {
+ let source = *preds.reduced_graph.node_data(edge.source());
+ let target = *preds.reduced_graph.node_data(edge.target());
match *target {
DepNode::MetaData(ref def_id) => {
// Metadata *targets* are always local metadata nodes. We have
}
_ => (),
}
+ debug!("serialize edge: {:?} -> {:?}", source, target);
+ let source = builder.map(source);
let target = builder.map(target);
- for &source in sources {
- let source = builder.map(source);
- edges.push((source, target.clone()));
- }
+ edges.entry(source).or_insert(vec![]).push(target);
}
if tcx.sess.opts.debugging_opts.incremental_dump_hash {
}
// Create the serialized dep-graph.
+ let edges = edges.into_iter()
+ .map(|(k, v)| SerializedEdgeSet { source: k, targets: v })
+ .collect();
let graph = SerializedDepGraph {
edges: edges,
hashes: preds.hashes
let mut def_id_hashes = FxHashMap();
- for (&target, sources) in &preds.inputs {
- let def_id = match *target {
- DepNode::MetaData(def_id) => {
- assert!(def_id.is_local());
- def_id
- }
+ for (index, target) in preds.reduced_graph.all_nodes().iter().enumerate() {
+ let index = NodeIndex(index);
+ let def_id = match *target.data {
+ DepNode::MetaData(def_id) if def_id.is_local() => def_id,
_ => continue,
};
// is the det. hash of the def-path. This is convenient
// because we can sort this to get a stable ordering across
// compilations, even if the def-ids themselves have changed.
- let mut hashes: Vec<(DepNode<u64>, Fingerprint)> = sources.iter()
- .map(|dep_node| {
- let hash_dep_node = dep_node.map_def(|&def_id| Some(def_id_hash(def_id))).unwrap();
- let hash = preds.hashes[dep_node];
- (hash_dep_node, hash)
- })
- .collect();
+ let mut hashes: Vec<(DepNode<u64>, Fingerprint)> =
+ preds.reduced_graph
+ .depth_traverse(index, INCOMING)
+ .map(|index| preds.reduced_graph.node_data(index))
+ .filter(|dep_node| HashContext::is_hashable(dep_node))
+ .map(|dep_node| {
+ let hash_dep_node = dep_node.map_def(|&def_id| Some(def_id_hash(def_id)))
+ .unwrap();
+ let hash = preds.hashes[dep_node];
+ (hash_dep_node, hash)
+ })
+ .collect();
hashes.sort();
let mut state = IchHasher::new();
if tcx.sess.opts.debugging_opts.incremental_dump_hash {
println!("metadata hash for {:?} is {}", def_id, hash);
- for dep_node in sources {
- println!("metadata hash for {:?} depends on {:?} with hash {}",
- def_id, dep_node, preds.hashes[dep_node]);
+ for pred_index in preds.reduced_graph.depth_traverse(index, INCOMING) {
+ let dep_node = preds.reduced_graph.node_data(pred_index);
+ if HashContext::is_hashable(&dep_node) {
+ println!("metadata hash for {:?} depends on {:?} with hash {}",
+ def_id, dep_node, preds.hashes[dep_node]);
+ }
}
}
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
rustc_const_eval = { path = "../librustc_const_eval" }
-rustc_i128 = { path = "../librustc_i128" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
#![cfg_attr(test, feature(test))]
#![feature(box_patterns)]
#![feature(box_syntax)]
+#![feature(i128_type)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
extern crate rustc_const_eval;
extern crate syntax_pos;
-extern crate rustc_i128;
-
pub use rustc::lint;
pub use rustc::middle;
pub use rustc::session;
id: LintId::of(LIFETIME_UNDERSCORE),
reference: "issue #36892 <https://github.com/rust-lang/rust/issues/36892>",
},
+ FutureIncompatibleInfo {
+ id: LintId::of(RESOLVE_TRAIT_ON_DEFAULTED_UNIT),
+ reference: "issue #39216 <https://github.com/rust-lang/rust/issues/39216>",
+ },
FutureIncompatibleInfo {
id: LintId::of(SAFE_EXTERN_STATICS),
reference: "issue #36247 <https://github.com/rust-lang/rust/issues/35112>",
id: LintId::of(LEGACY_IMPORTS),
reference: "issue #38260 <https://github.com/rust-lang/rust/issues/38260>",
},
+ FutureIncompatibleInfo {
+ id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY),
+ reference: "issue #39207 <https://github.com/rust-lang/rust/issues/39207>",
+ },
]);
// Register renamed and removed lints
use rustc::hir;
-use rustc_i128::{i128, u128};
-
declare_lint! {
UNUSED_COMPARISONS,
Warn,
consider using a `*const libc::c_char`")
}
- ty::TyTuple(_) => {
+ ty::TyTuple(..) => {
FfiUnsafe("found Rust tuple type in foreign module; \
consider using a struct instead")
}
let t = cx.tables.expr_ty(&expr);
let warned = match t.sty {
- ty::TyTuple(ref tys) if tys.is_empty() => return,
+ ty::TyTuple(ref tys, _) if tys.is_empty() => return,
ty::TyNever => return,
ty::TyBool => return,
ty::TyAdt(def, _) => {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// FIXME: Rename 'DIGlobalVariable' to 'DIGlobalVariableExpression'
+// once support for LLVM 3.9 is dropped.
+//
+// This method was changed in this LLVM patch:
+// https://reviews.llvm.org/D26769
+
use debuginfo::{DIBuilderRef, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType,
DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable,
DIGlobalVariable, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator,
Name: *const c_char)
-> ValueRef;
pub fn LLVMRustAddHandler(CatchSwitch: ValueRef, Handler: BasicBlockRef);
- pub fn LLVMRustSetPersonalityFn(B: BuilderRef, Pers: ValueRef);
+ pub fn LLVMSetPersonalityFn(Func: ValueRef, Pers: ValueRef);
// Add a case to the switch instruction
pub fn LLVMAddCase(Switch: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef);
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
rustc_llvm = { path = "../librustc_llvm" }
-rustc_i128 = { path = "../librustc_i128" }
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
syntax_ext = { path = "../libsyntax_ext" }
GateIssue::Language,
"is feature gated");
}
+ if lib.kind == cstore::NativeStaticNobundle && !sess.features.borrow().static_nobundle {
+ feature_gate::emit_feature_err(&sess.parse_sess,
+ "static_nobundle",
+ span.unwrap(),
+ GateIssue::Language,
+ "kind=\"static-nobundle\" is feature gated");
+ }
cstore.add_used_library(lib);
}
use proc_macro::TokenStream;
use proc_macro::__internal::Registry;
use rustc_back::dynamic_lib::DynamicLibrary;
- use syntax_ext::deriving::custom::CustomDerive;
+ use syntax_ext::deriving::custom::ProcMacroDerive;
use syntax_ext::proc_macro_impl::AttrProcMacro;
let path = match dylib {
expand: fn(TokenStream) -> TokenStream,
attributes: &[&'static str]) {
let attrs = attributes.iter().cloned().map(Symbol::intern).collect();
- let derive = SyntaxExtension::CustomDerive(
- Box::new(CustomDerive::new(expand, attrs))
+ let derive = SyntaxExtension::ProcMacroDerive(
+ Box::new(ProcMacroDerive::new(expand, attrs))
);
self.0.push((Symbol::intern(trait_name), Rc::new(derive)));
}
for id in self.get_foreign_items_of_kind(cstore::NativeStatic) {
self.cstore.add_statically_included_foreign_item(id);
}
+ for id in self.get_foreign_items_of_kind(cstore::NativeStaticNobundle) {
+ self.cstore.add_statically_included_foreign_item(id);
+ }
}
fn register_dllimport_foreign_items(&mut self) {
}).and_then(|a| a.value_str()).map(Symbol::as_str);
let kind = match kind.as_ref().map(|s| &s[..]) {
Some("static") => cstore::NativeStatic,
+ Some("static-nobundle") => cstore::NativeStaticNobundle,
Some("dylib") => cstore::NativeUnknown,
Some("framework") => cstore::NativeFramework,
Some(k) => {
use syntax_pos;
pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference};
-pub use rustc::middle::cstore::{NativeStatic, NativeFramework, NativeUnknown};
+pub use rustc::middle::cstore::NativeLibraryKind::*;
pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource};
// A map from external crate numbers (as decoded from some crate file) to
use syntax::ast;
use syntax::codemap;
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP};
-use rustc_i128::{u128, i128};
pub struct DecodeContext<'a, 'tcx: 'a> {
opaque: opaque::Decoder<'a>,
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
use rustc::hir::intravisit;
-use rustc_i128::{u128, i128};
-
use super::index_builder::{FromId, IndexBuilder, Untracked};
pub struct EncodeContext<'a, 'tcx: 'a> {
let struct_id = tcx.hir.as_local_node_id(adt_def_id).unwrap();
let struct_vis = &tcx.hir.expect_item(struct_id).vis;
+ let mut ctor_vis = ty::Visibility::from_hir(struct_vis, struct_id, tcx);
+ for field in &variant.fields {
+ if ctor_vis.is_at_least(field.vis, tcx) {
+ ctor_vis = field.vis;
+ }
+ }
Entry {
kind: EntryKind::Struct(self.lazy(&data)),
- visibility: self.lazy(&ty::Visibility::from_hir(struct_vis, struct_id, tcx)),
+ visibility: self.lazy(&ctor_vis),
span: self.lazy(&tcx.def_span(def_id)),
attributes: LazySeq::empty(),
children: LazySeq::empty(),
#![feature(box_patterns)]
#![feature(conservative_impl_trait)]
#![feature(core_intrinsics)]
+#![feature(i128_type)]
#![feature(proc_macro_internals)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
extern crate rustc_const_math;
extern crate rustc_data_structures;
extern crate rustc_llvm;
-extern crate rustc_i128;
mod diagnostics;
use std::marker::PhantomData;
-use rustc_i128::u128;
-
pub fn rustc_version() -> String {
format!("rustc {}",
option_env!("CFG_VERSION").unwrap_or("unknown version"))
rustc_const_math = { path = "../librustc_const_math" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_bitflags = { path = "../librustc_bitflags" }
-rustc_i128 = { path = "../librustc_i128" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
pub fn ast_block(&mut self,
destination: &Lvalue<'tcx>,
- // FIXME(#32959): temporary measure for the issue
- dest_is_unit: bool,
mut block: BasicBlock,
ast_block: &'tcx hir::Block)
-> BlockAnd<()> {
// of the block.
if let Some(expr) = expr {
unpack!(block = this.into(destination, block, expr));
- } else if dest_is_unit {
- // FIXME(#31472)
+ } else {
let source_info = this.source_info(span);
this.cfg.push_assign_unit(block, source_info, destination);
}
use rustc_const_math::{ConstMathErr, Op};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::Idx;
-use rustc_i128::i128;
use build::{BlockAnd, BlockAndExtension, Builder};
use build::expr::category::{Category, RvalueFunc};
let source_info = self.source_info(span);
let bool_ty = self.hir.bool_ty();
if self.hir.check_overflow() && op.is_checkable() && ty.is_integral() {
- let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty]);
+ let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty], false);
let result_value = self.temp(result_tup);
self.cfg.push_assign(block, source_info,
this.in_scope(extent, block, |this| this.into(destination, block, value))
}
ExprKind::Block { body: ast_block } => {
- this.ast_block(destination, expr.ty.is_nil(), block, ast_block)
+ this.ast_block(destination, block, ast_block)
}
ExprKind::Match { discriminant, arms } => {
this.match_expr(destination, expr_span, block, discriminant, arms)
#![feature(associated_consts)]
#![feature(box_patterns)]
+#![feature(i128_type)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
#![feature(staged_api)]
extern crate rustc_const_math;
extern crate rustc_const_eval;
-extern crate rustc_i128;
-
pub mod diagnostics;
pub mod build;
let mir = tcx.alloc_mir(mir);
let def_id = tcx.hir.local_def_id(src.item_id());
- assert!(tcx.mir_map.borrow_mut().insert(def_id, mir).is_none());
+ tcx.mir_map.borrow_mut().insert(def_id, mir);
});
let body = self.tcx.hir.body(body_id);
})
}
}
- ty::TyTuple(tys) => {
+ ty::TyTuple(tys, _) => {
return match tys.get(field.index()) {
Some(&ty) => Ok(ty),
None => Err(FieldAccessError::OutOfRange {
```
"##,
-E0450: r##"
-A tuple constructor was invoked while some of its fields are private. Erroneous
-code example:
-
-```compile_fail,E0450
-mod Bar {
- pub struct Foo(isize);
-}
-
-let f = Bar::Foo(0); // error: cannot invoke tuple struct constructor with
- // private fields
-```
-
-To solve this issue, please ensure that all of the fields of the tuple struct
-are public. Alternatively, provide a `new()` method to the tuple struct to
-construct it from a given inner value. Example:
-
-```
-mod Bar {
- pub struct Foo(pub isize); // we set its field to public
-}
-
-let f = Bar::Foo(0); // ok!
-
-// or:
-mod bar {
- pub struct Foo(isize);
-
- impl Foo {
- pub fn new(x: isize) -> Foo {
- Foo(x)
- }
- }
-}
-
-let f = bar::Foo::new(1);
-```
-"##,
-
E0451: r##"
A struct constructor with private fields was invoked. Erroneous code example:
"##,
}
+
+register_diagnostics! {
+// E0450, moved into resolve
+}
use rustc::dep_graph::DepNode;
use rustc::hir::{self, PatKind};
-use rustc::hir::def::{self, Def, CtorKind};
+use rustc::hir::def::{self, Def};
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::itemlikevisit::DeepVisitor;
}
}
}
- hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
- if let Def::StructCtor(_, CtorKind::Fn) = path.def {
- let adt_def = self.tcx.expect_variant_def(path.def);
- let private_indexes = adt_def.fields.iter().enumerate().filter(|&(_, field)| {
- !field.vis.is_accessible_from(self.curitem, self.tcx)
- }).map(|(i, _)| i).collect::<Vec<_>>();
-
- if !private_indexes.is_empty() {
- let mut error = struct_span_err!(self.tcx.sess, expr.span, E0450,
- "cannot invoke tuple struct constructor \
- with private fields");
- error.span_label(expr.span,
- &format!("cannot construct with a private field"));
-
- if let Some(node_id) = self.tcx.hir.as_local_node_id(adt_def.did) {
- let node = self.tcx.hir.find(node_id);
- if let Some(hir::map::NodeStructCtor(vdata)) = node {
- for i in private_indexes {
- error.span_label(vdata.fields()[i].span,
- &format!("private field declared here"));
- }
- }
- }
- error.emit();
- }
- }
- }
_ => {}
}
let def = Def::Struct(self.definitions.local_def_id(item.id));
self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
- // If this is a tuple or unit struct, define a name
- // in the value namespace as well.
- if !struct_def.is_struct() {
- let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()),
- CtorKind::from_ast(struct_def));
- self.define(parent, ident, ValueNS, (ctor_def, vis, sp, expansion));
- }
-
// Record field names for error reporting.
+ let mut ctor_vis = vis;
let field_names = struct_def.fields().iter().filter_map(|field| {
- self.resolve_visibility(&field.vis);
+ let field_vis = self.resolve_visibility(&field.vis);
+ if ctor_vis.is_at_least(field_vis, &*self) {
+ ctor_vis = field_vis;
+ }
field.ident.map(|ident| ident.name)
}).collect();
let item_def_id = self.definitions.local_def_id(item.id);
self.insert_field_names(item_def_id, field_names);
+
+ // If this is a tuple or unit struct, define a name
+ // in the value namespace as well.
+ if !struct_def.is_struct() {
+ let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()),
+ CtorKind::from_ast(struct_def));
+ self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion));
+ self.struct_constructors.insert(def.def_id(), (ctor_def, ctor_vis));
+ }
}
ItemKind::Union(ref vdata, _) => {
Def::Variant(..) | Def::TyAlias(..) => {
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
}
- Def::Fn(..) | Def::Static(..) | Def::Const(..) |
- Def::VariantCtor(..) | Def::StructCtor(..) => {
+ Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => {
+ self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
+ }
+ Def::StructCtor(..) => {
self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
+
+ if let Some(struct_def_id) =
+ self.session.cstore.def_key(def_id).parent
+ .map(|index| DefId { krate: def_id.krate, index: index }) {
+ self.struct_constructors.insert(struct_def_id, (def, vis));
+ }
}
Def::Trait(..) => {
let module_kind = ModuleKind::Def(def, ident.name);
"an `extern crate` loading macros must be at the crate root");
} else if !self.use_extern_macros && !used &&
self.session.cstore.dep_kind(module.def_id().unwrap().krate).macros_only() {
- let msg = "custom derive crates and `#[no_link]` crates have no effect without \
+ let msg = "proc macro crates and `#[no_link]` crates have no effect without \
`#[macro_use]`";
self.session.span_warn(item.span, msg);
used = true; // Avoid the normal unused extern crate warning
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
use rustc::ty;
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
-use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet};
+use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
use syntax::ext::hygiene::{Mark, SyntaxContext};
use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy};
warned_proc_macros: FxHashSet<Name>,
potentially_unused_imports: Vec<&'a ImportDirective<'a>>,
+
+ // This table maps struct IDs into struct constructor IDs,
+ // it's not used during normal resolution, only for better error reporting.
+ struct_constructors: DefIdMap<(Def, ty::Visibility)>,
}
pub struct ResolverArenas<'a> {
proc_macro_enabled: features.proc_macro,
warned_proc_macros: FxHashSet(),
potentially_unused_imports: Vec::new(),
+ struct_constructors: DefIdMap(),
}
}
_ => {}
},
_ if ns == ValueNS && is_struct_like(def) => {
+ if let Def::Struct(def_id) = def {
+ if let Some((ctor_def, ctor_vis))
+ = this.struct_constructors.get(&def_id).cloned() {
+ if is_expected(ctor_def) && !this.is_accessible(ctor_vis) {
+ err.span_label(span, &format!("constructor is not visible \
+ here due to private fields"));
+ }
+ }
+ }
err.span_label(span, &format!("did you mean `{} {{ /* fields */ }}`?",
path_str));
return err;
if is_expected(resolution.base_def) || resolution.base_def == Def::Err {
resolution
} else {
- report_errors(self, Some(resolution.base_def))
+ // Add a temporary hack to smooth the transition to new struct ctor
+ // visibility rules. See #38932 for more details.
+ let mut res = None;
+ if let Def::Struct(def_id) = resolution.base_def {
+ if let Some((ctor_def, ctor_vis))
+ = self.struct_constructors.get(&def_id).cloned() {
+ if is_expected(ctor_def) && self.is_accessible(ctor_vis) {
+ let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY;
+ self.session.add_lint(lint, id, span,
+ "private struct constructors are not usable through \
+ reexports in outer modules".to_string());
+ res = Some(PathResolution::new(ctor_def));
+ }
+ }
+ }
+
+ res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def)))
}
}
Some(resolution) if source.defer_to_typeck() => {
}
result
}
+
+ fn resolve_builtin_macro(&mut self, tname: Name) -> Result<Rc<SyntaxExtension>, Determinacy> {
+ match self.builtin_macros.get(&tname).cloned() {
+ Some(binding) => Ok(binding.get_macro(self)),
+ None => Err(Determinacy::Undetermined),
+ }
+ }
+
+ fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
+ -> Result<Rc<SyntaxExtension>, Determinacy> {
+ let ast::Path { span, .. } = *path;
+ match self.resolve_macro(scope, path, false) {
+ Ok(ext) => match *ext {
+ SyntaxExtension::BuiltinDerive(..) |
+ SyntaxExtension::ProcMacroDerive(..) => Ok(ext),
+ _ => Err(Determinacy::Determined),
+ },
+ Err(Determinacy::Undetermined) if force => {
+ let msg = format!("cannot find derive macro `{}` in this scope", path);
+ let mut err = self.session.struct_span_err(span, &msg);
+ err.emit();
+ Err(Determinacy::Determined)
+ },
+ Err(err) => Err(err),
+ }
+ }
}
impl<'a> Resolver<'a> {
let names = resolutions.iter().filter_map(|(&(ref i, _), resolution)| {
if *i == ident { return None; } // Never suggest the same name
match *resolution.borrow() {
- NameResolution { binding: Some(_), .. } => Some(&i.name),
+ NameResolution { binding: Some(name_binding), .. } => {
+ match name_binding.kind {
+ NameBindingKind::Import { binding, .. } => {
+ match binding.kind {
+ // Never suggest the name that has binding error
+ // i.e. the name that cannot be previously resolved
+ NameBindingKind::Def(Def::Err) => return None,
+ _ => Some(&i.name),
+ }
+ },
+ _ => Some(&i.name),
+ }
+ },
NameResolution { single_imports: SingleImports::None, .. } => None,
_ => Some(&i.name),
}
}.lower(self.tcx));
}
}
- ty::TyTuple(_) => {}
+ ty::TyTuple(..) => {}
_ => span_bug!(ex.span,
"Expected struct or tuple type, found {:?}",
ty),
-> Option<TypeRefData> {
self.lookup_ref_id(trait_ref.ref_id).and_then(|def_id| {
let span = trait_ref.path.span;
+ if generated_code(span) {
+ return None;
+ }
let sub_span = self.span_utils.sub_span_for_type_name(span).or(Some(span));
filter!(self.span_utils, sub_span, span, None);
Some(TypeRefData {
rustc_errors = { path = "../librustc_errors" }
rustc_incremental = { path = "../librustc_incremental" }
rustc_llvm = { path = "../librustc_llvm" }
-rustc_i128 = { path = "../librustc_i128" }
rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
assert!(!sig.variadic && extra_args.is_empty());
match sig.inputs().last().unwrap().sty {
- ty::TyTuple(ref tupled_arguments) => {
+ ty::TyTuple(ref tupled_arguments, _) => {
inputs = &sig.inputs()[0..sig.inputs().len() - 1];
&tupled_arguments[..]
}
monomorphize::field_ty(cx.tcx(), substs, f)
}).collect::<Vec<_>>()
},
- ty::TyTuple(fields) => fields.to_vec(),
+ ty::TyTuple(fields, _) => fields.to_vec(),
ty::TyClosure(def_id, substs) => {
if variant_index > 0 { bug!("{} is a closure, which only has one variant", t);}
substs.upvar_tys(def_id, cx.tcx()).collect()
use rustc::hir::def_id::CrateNum;
use rustc::hir::svh::Svh;
use rustc_back::tempdir::TempDir;
+use rustc_back::PanicStrategy;
use rustc_incremental::IncrementalHashesMap;
use std::ascii;
for lib in sess.cstore.used_libraries() {
match lib.kind {
NativeLibraryKind::NativeStatic => {}
+ NativeLibraryKind::NativeStaticNobundle |
NativeLibraryKind::NativeFramework |
NativeLibraryKind::NativeUnknown => continue,
}
for lib in all_native_libs.iter().filter(|l| relevant_lib(sess, l)) {
let name = match lib.kind {
+ NativeLibraryKind::NativeStaticNobundle |
NativeLibraryKind::NativeUnknown => "library",
NativeLibraryKind::NativeFramework => "framework",
// These are included, no need to print them
cmd.arg(root.join(obj));
}
+ if sess.target.target.options.is_like_emscripten &&
+ sess.panic_strategy() == PanicStrategy::Abort {
+ cmd.args(&["-s", "DISABLE_EXCEPTION_CATCHING=1"]);
+ }
+
{
let mut linker = trans.linker_info.to_linker(&mut cmd, &sess);
link_args(&mut *linker, sess, crate_type, tmpdir,
// on other dylibs (e.g. other native deps).
add_local_native_libraries(cmd, sess);
add_upstream_rust_crates(cmd, sess, crate_type, tmpdir);
- add_upstream_native_libraries(cmd, sess);
+ add_upstream_native_libraries(cmd, sess, crate_type);
// # Telling the linker what we're doing
match lib.kind {
NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()),
NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()),
+ NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(&lib.name.as_str()),
NativeLibraryKind::NativeStatic => bug!(),
}
}
// generic function calls a native function, then the generic function must
// be instantiated in the target crate, meaning that the native symbol must
// also be resolved in the target crate.
-fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session) {
+fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session, crate_type: config::CrateType) {
// Be sure to use a topological sorting of crates because there may be
// interdependencies between native libraries. When passing -nodefaultlibs,
// for example, almost all native libraries depend on libc, so we have to
// This passes RequireStatic, but the actual requirement doesn't matter,
// we're just getting an ordering of crate numbers, we're not worried about
// the paths.
+ let formats = sess.dependency_formats.borrow();
+ let data = formats.get(&crate_type).unwrap();
+
let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic);
for (cnum, _) in crates {
for lib in sess.cstore.native_libraries(cnum) {
match lib.kind {
NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()),
NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()),
-
+ NativeLibraryKind::NativeStaticNobundle => {
+ // Link "static-nobundle" native libs only if the crate they originate from
+ // is being linked statically to the current crate. If it's linked dynamically
+ // or is an rlib already included via some other dylib crate, the symbols from
+ // native libs will have already been included in that dylib.
+ if data[cnum.as_usize() - 1] == Linkage::Static {
+ cmd.link_staticlib(&lib.name.as_str())
+ }
+ },
// ignore statically included native libraries here as we've
// already included them when we included the rust library
// previously
writeln!(f, "LIBRARY")?;
writeln!(f, "EXPORTS")?;
for symbol in self.info.exports[&crate_type].iter() {
+ debug!(" _{}", symbol);
writeln!(f, " {}", symbol)?;
}
Ok(())
pub fn set_personality_fn(&self, personality: ValueRef) {
unsafe {
- llvm::LLVMRustSetPersonalityFn(self.llbuilder, personality);
+ llvm::LLVMSetPersonalityFn(self.llfn(), personality);
}
}
}
};
let sig = tcx.erase_late_bound_regions_and_normalize(sig);
- let tuple_input_ty = tcx.intern_tup(sig.inputs());
+ let tuple_input_ty = tcx.intern_tup(sig.inputs(), false);
let sig = tcx.mk_fn_sig(
[bare_fn_ty_maybe_ref, tuple_input_ty].iter().cloned(),
sig.output(),
output.push(TransItem::DropGlue(DropGlueKind::Ty(inner_type)));
}
}
- ty::TyTuple(args) => {
+ ty::TyTuple(args, _) => {
for arg in args {
let arg = glue::get_drop_glue_type(scx, arg);
if scx.type_needs_drop(arg) {
use syntax::symbol::InternedString;
use syntax_pos::Span;
-use rustc_i128::u128;
-
pub use context::{CrateContext, SharedCrateContext};
pub fn type_is_fat_ptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
}
}))
}
- ty::TyTuple(tys) => {
+ ty::TyTuple(tys, _) => {
if tys.len() != 2 {
return None;
}
}
}
-pub fn C_big_integral(t: Type, u: u128, sign_extend: bool) -> ValueRef {
- if ::std::mem::size_of::<u128>() == 16 {
- unsafe {
- let words = [u as u64, u.wrapping_shr(64) as u64];
- llvm::LLVMConstIntOfArbitraryPrecision(t.to_ref(), 2, words.as_ptr())
- }
- } else {
- // SNAP: remove after snapshot
- C_integral(t, u as u64, sign_extend)
+pub fn C_big_integral(t: Type, u: u128) -> ValueRef {
+ unsafe {
+ let words = [u as u64, u.wrapping_shr(64) as u64];
+ llvm::LLVMConstIntOfArbitraryPrecision(t.to_ref(), 2, words.as_ptr())
}
}
}
#[inline]
-#[cfg(stage0)]
-fn hi_lo_to_u128(lo: u64, _: u64) -> u128 {
- lo as u128
-}
-
-#[inline]
-#[cfg(not(stage0))]
fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
((hi as u128) << 64) | (lo as u128)
}
// return type
signature_metadata.push(match signature.output().sty {
- ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(),
+ ty::TyTuple(ref tys, _) if tys.is_empty() => ptr::null_mut(),
_ => type_metadata(cx, signature.output(), span)
});
ty::TyFloat(_) => {
MetadataCreationResult::new(basic_type_metadata(cx, t), false)
}
- ty::TyTuple(ref elements) if elements.is_empty() => {
+ ty::TyTuple(ref elements, _) if elements.is_empty() => {
MetadataCreationResult::new(basic_type_metadata(cx, t), false)
}
ty::TyArray(typ, len) => {
usage_site_span).finalize(cx)
}
},
- ty::TyTuple(ref elements) => {
+ ty::TyTuple(ref elements, _) => {
prepare_tuple_metadata(cx,
t,
&elements[..],
let (name, encoding) = match t.sty {
ty::TyNever => ("!", DW_ATE_unsigned),
- ty::TyTuple(ref elements) if elements.is_empty() =>
+ ty::TyTuple(ref elements, _) if elements.is_empty() =>
("()", DW_ATE_unsigned),
ty::TyBool => ("bool", DW_ATE_boolean),
ty::TyChar => ("char", DW_ATE_unsigned_char),
// Return type -- llvm::DIBuilder wants this at index 0
signature.push(match sig.output().sty {
- ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(),
+ ty::TyTuple(ref tys, _) if tys.is_empty() => ptr::null_mut(),
_ => type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP)
});
}
if abi == Abi::RustCall && !sig.inputs().is_empty() {
- if let ty::TyTuple(args) = sig.inputs()[sig.inputs().len() - 1].sty {
+ if let ty::TyTuple(args, _) = sig.inputs()[sig.inputs().len() - 1].sty {
for &argument_type in args {
signature.push(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP));
}
push_item_name(cx, def.did, qualified, output);
push_type_params(cx, substs, output);
},
- ty::TyTuple(component_types) => {
+ ty::TyTuple(component_types, _) => {
output.push('(');
for &component_type in component_types {
push_debuginfo_type_name(cx, component_type, true, output);
#[inline]
pub fn debug_context<'a, 'tcx>(cx: &'a CrateContext<'a, 'tcx>)
-> &'a CrateDebugContext<'tcx> {
- let debug_context: &'a CrateDebugContext<'tcx> = cx.dbg_cx().as_ref().unwrap();
- debug_context
+ cx.dbg_cx().as_ref().unwrap()
}
#[inline]
cx = tvec::slice_for_each(&cx, ptr.llval, unit_ty, ptr.llextra,
|bb, vv| drop_ty(bb, LvalueRef::new_sized_ty(vv, unit_ty)));
}
- ty::TyTuple(ref args) => {
+ ty::TyTuple(ref args, _) => {
for (i, arg) in args.iter().enumerate() {
let llfld_a = ptr.trans_field_ptr(&cx, i);
drop_ty(&cx, LvalueRef::new_sized_ty(llfld_a, *arg));
use rustc::session::Session;
use syntax_pos::Span;
-use rustc_i128::u128;
-
use std::cmp::Ordering;
use std::iter;
#![feature(const_fn)]
#![feature(custom_attribute)]
#![allow(unused_attributes)]
+#![feature(i128_type)]
#![feature(libc)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#[macro_use]
#[no_link]
extern crate rustc_bitflags;
-extern crate rustc_i128;
#[macro_use] extern crate log;
#[macro_use] extern crate syntax;
let tuple = self.trans_operand(bcx, operand);
let arg_types = match tuple.ty.sty {
- ty::TyTuple(ref tys) => tys,
+ ty::TyTuple(ref tys, _) => tys,
_ => span_bug!(self.mir.span,
"bad final argument to \"rust-call\" fn {:?}", tuple.ty)
};
use super::operand::{OperandRef, OperandValue};
use super::MirContext;
-use rustc_i128::{u128, i128};
-
/// A sized constant rvalue.
/// The LLVM type might not be the same for a single Rust type,
/// e.g. each enum variant would have its own LLVM struct type.
ConstVal::Integral(I16(v)) => C_integral(Type::i16(ccx), v as u64, true),
ConstVal::Integral(I32(v)) => C_integral(Type::i32(ccx), v as u64, true),
ConstVal::Integral(I64(v)) => C_integral(Type::i64(ccx), v as u64, true),
- ConstVal::Integral(I128(v)) => C_big_integral(Type::i128(ccx), v as u128, true),
+ ConstVal::Integral(I128(v)) => C_big_integral(Type::i128(ccx), v as u128),
ConstVal::Integral(Isize(v)) => {
let i = v.as_i64(ccx.tcx().sess.target.int_type);
C_integral(Type::int(ccx), i as u64, true)
ConstVal::Integral(U16(v)) => C_integral(Type::i16(ccx), v as u64, false),
ConstVal::Integral(U32(v)) => C_integral(Type::i32(ccx), v as u64, false),
ConstVal::Integral(U64(v)) => C_integral(Type::i64(ccx), v, false),
- ConstVal::Integral(U128(v)) => C_big_integral(Type::i128(ccx), v, false),
+ ConstVal::Integral(U128(v)) => C_big_integral(Type::i128(ccx), v),
ConstVal::Integral(Usize(v)) => {
let u = v.as_u64(ccx.tcx().sess.target.uint_type);
C_integral(Type::int(ccx), u, false)
let rhs = self.const_operand(rhs, span)?;
let ty = lhs.ty;
let val_ty = op.ty(tcx, lhs.ty, rhs.ty);
- let binop_ty = tcx.intern_tup(&[val_ty, tcx.types.bool]);
+ let binop_ty = tcx.intern_tup(&[val_ty, tcx.types.bool], false);
let (lhs, rhs) = (lhs.llval, rhs.llval);
assert!(!ty.is_fp());
mircx.cleanup_kinds.iter_enumerated().map(|(bb, cleanup_kind)| {
if let CleanupKind::Funclet = *cleanup_kind {
let bcx = mircx.get_builder(bb);
- bcx.set_personality_fn(mircx.ccx.eh_personality());
+ unsafe {
+ llvm::LLVMSetPersonalityFn(mircx.llfn, mircx.ccx.eh_personality());
+ }
if base::wants_msvc_seh(ccx.sess()) {
return Some(Funclet::new(bcx.cleanup_pad(None, &[])));
}
// individual LLVM function arguments.
let tupled_arg_tys = match arg_ty.sty {
- ty::TyTuple(ref tys) => tys,
+ ty::TyTuple(ref tys, _) => tys,
_ => bug!("spread argument isn't a tuple?!")
};
lhs.immediate(), rhs.immediate(),
lhs.ty);
let val_ty = op.ty(bcx.tcx(), lhs.ty, rhs.ty);
- let operand_ty = bcx.tcx().intern_tup(&[val_ty, bcx.tcx().types.bool]);
+ let operand_ty = bcx.tcx().intern_tup(&[val_ty, bcx.tcx().types.bool], false);
let operand = OperandRef {
val: result,
ty: operand_ty
self.push_def_path(adt_def.did, output);
self.push_type_params(substs, iter::empty(), output);
},
- ty::TyTuple(component_types) => {
+ ty::TyTuple(component_types, _) => {
output.push('(');
for &component_type in component_types {
self.push_type_name(component_type, output);
Type::array(&llty, size)
}
- ty::TyTuple(ref tys) if tys.is_empty() => {
+ ty::TyTuple(ref tys, _) if tys.is_empty() => {
Type::nil(cx)
}
let sig = cx.tcx().erase_late_bound_regions_and_normalize(&f.sig);
FnType::new(cx, f.abi, &sig, &[]).llvm_type(cx).ptr_to()
}
- ty::TyTuple(ref tys) if tys.is_empty() => Type::nil(cx),
+ ty::TyTuple(ref tys, _) if tys.is_empty() => Type::nil(cx),
ty::TyTuple(..) => {
adt::type_of(cx, t)
}
use hir::def::Def;
use hir::def_id::DefId;
use middle::resolve_lifetime as rl;
-use rustc::lint;
use rustc::ty::subst::{Kind, Subst, Substs};
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
}
Some(&rl::Region::LateBound(debruijn, id)) => {
- // If this region is declared on a function, it will have
- // an entry in `late_bound`, but if it comes from
- // `for<'a>` in some type or something, it won't
- // necessarily have one. In that case though, we won't be
- // changed from late to early bound, so we can just
- // substitute false.
- let issue_32330 = tcx.named_region_map
- .late_bound
- .get(&id)
- .cloned()
- .unwrap_or(ty::Issue32330::WontChange);
let name = tcx.hir.name(id);
tcx.mk_region(ty::ReLateBound(debruijn,
- ty::BrNamed(tcx.hir.local_def_id(id), name, issue_32330)))
+ ty::BrNamed(tcx.hir.local_def_id(id), name)))
}
Some(&rl::Region::LateBoundAnon(debruijn, index)) => {
}
Some(&rl::Region::Free(scope, id)) => {
- // As in Region::LateBound above, could be missing for some late-bound
- // regions, but also for early-bound regions.
- let issue_32330 = tcx.named_region_map
- .late_bound
- .get(&id)
- .cloned()
- .unwrap_or(ty::Issue32330::WontChange);
let name = tcx.hir.name(id);
tcx.mk_region(ty::ReFree(ty::FreeRegion {
scope: scope.to_code_extent(&tcx.region_maps),
- bound_region: ty::BrNamed(tcx.hir.local_def_id(id), name, issue_32330)
+ bound_region: ty::BrNamed(tcx.hir.local_def_id(id), name)
}))
// (*) -- not late-bound, won't change
span: output_span
};
- (self.tcx().mk_ty(ty::TyTuple(inputs)), output_binding)
+ (self.tcx().mk_ty(ty::TyTuple(inputs, false)), output_binding)
}
/// Instantiates the path for the given trait reference, assuming that it's
fn ast_type_binding_to_poly_projection_predicate(
&self,
- path_id: ast::NodeId,
+ _path_id: ast::NodeId,
trait_ref: ty::PolyTraitRef<'tcx>,
binding: &ConvertedBinding<'tcx>)
-> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported>
debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
for br in late_bound_in_ty.difference(&late_bound_in_trait_ref) {
let br_name = match *br {
- ty::BrNamed(_, name, _) => name,
+ ty::BrNamed(_, name) => name,
_ => {
span_bug!(
binding.span,
br);
}
};
- tcx.sess.add_lint(
- lint::builtin::HR_LIFETIME_IN_ASSOC_TYPE,
- path_id,
- binding.span,
- format!("binding for associated type `{}` references lifetime `{}`, \
- which does not appear in the trait input types",
- binding.item_name, br_name));
+ struct_span_err!(tcx.sess,
+ binding.span,
+ E0582,
+ "binding for associated type `{}` references lifetime `{}`, \
+ which does not appear in the trait input types",
+ binding.item_name, br_name)
+ .emit();
}
// Simple case: X is defined in the current trait.
tcx.types.never
},
hir::TyTup(ref fields) => {
- tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t)))
+ tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t)), false)
}
hir::TyBareFn(ref bf) => {
require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(&output);
for br in late_bound_in_ret.difference(&late_bound_in_args) {
let br_name = match *br {
- ty::BrNamed(_, name, _) => name,
+ ty::BrNamed(_, name) => name,
_ => {
span_bug!(
bf.decl.output.span(),
br);
}
};
- tcx.sess.add_lint(
- lint::builtin::HR_LIFETIME_IN_ASSOC_TYPE,
- ast_ty.id,
- ast_ty.span,
- format!("return type references lifetime `{}`, \
- which does not appear in the trait input types",
- br_name));
+ struct_span_err!(tcx.sess,
+ ast_ty.span,
+ E0581,
+ "return type references lifetime `{}`, \
+ which does not appear in the fn input types",
+ br_name)
+ .emit();
}
tcx.mk_fn_ptr(bare_fn_ty)
}
let mut expected_len = elements.len();
if ddpos.is_some() {
// Require known type only when `..` is present
- if let ty::TyTuple(ref tys) =
+ if let ty::TyTuple(ref tys, _) =
self.structurally_resolved_type(pat.span, expected).sty {
expected_len = tys.len();
}
// from all tuple elements isn't trivial.
TypeVariableOrigin::TypeInference(pat.span)));
let element_tys = tcx.mk_type_list(element_tys_iter);
- let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys));
+ let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys, false));
self.demand_eqtype(pat.span, expected, pat_ty);
for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
self.check_pat(elem, &element_tys[i]);
let t_cast = self.cast_ty;
let t_expr = self.expr_ty;
if t_cast.is_numeric() && t_expr.is_numeric() {
- fcx.tcx.sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS,
- self.expr.id,
- self.span,
- format!("trivial numeric cast: `{}` as `{}`. Cast can be \
- replaced by coercion, this might require type \
- ascription or a temporary variable",
- fcx.ty_to_string(t_expr),
- fcx.ty_to_string(t_cast)));
+ fcx.tables.borrow_mut().lints.add_lint(
+ lint::builtin::TRIVIAL_NUMERIC_CASTS,
+ self.expr.id,
+ self.span,
+ format!("trivial numeric cast: `{}` as `{}`. Cast can be \
+ replaced by coercion, this might require type \
+ ascription or a temporary variable",
+ fcx.ty_to_string(t_expr),
+ fcx.ty_to_string(t_cast)));
} else {
- fcx.tcx.sess.add_lint(lint::builtin::TRIVIAL_CASTS,
- self.expr.id,
- self.span,
- format!("trivial cast: `{}` as `{}`. Cast can be \
- replaced by coercion, this might require type \
- ascription or a temporary variable",
- fcx.ty_to_string(t_expr),
- fcx.ty_to_string(t_cast)));
+ fcx.tables.borrow_mut().lints.add_lint(
+ lint::builtin::TRIVIAL_CASTS,
+ self.expr.id,
+ self.span,
+ format!("trivial cast: `{}` as `{}`. Cast can be \
+ replaced by coercion, this might require type \
+ ascription or a temporary variable",
+ fcx.ty_to_string(t_expr),
+ fcx.ty_to_string(t_cast)));
}
}
// Tuple up the arguments and insert the resulting function type into
// the `closures` table.
fn_ty.sig.0 = self.tcx.mk_fn_sig(
- iter::once(self.tcx.intern_tup(fn_ty.sig.skip_binder().inputs())),
+ iter::once(self.tcx.intern_tup(fn_ty.sig.skip_binder().inputs(), false)),
fn_ty.sig.skip_binder().output(),
fn_ty.sig.variadic()
);
arg_param_ty);
let input_tys = match arg_param_ty.sty {
- ty::TyTuple(tys) => tys.into_iter(),
+ ty::TyTuple(tys, _) => tys.into_iter(),
_ => {
return None;
}
Ok(())
}
- ty::TyTuple(tys) => {
+ ty::TyTuple(tys, _) => {
for ty in tys {
iterate_over_potentially_unsafe_regions_in_type(cx, context, ty, depth+1)?
}
"cxchg" | "cxchgweak" => (1, vec![tcx.mk_mut_ptr(param(ccx, 0)),
param(ccx, 0),
param(ccx, 0)],
- tcx.intern_tup(&[param(ccx, 0), tcx.types.bool])),
+ tcx.intern_tup(&[param(ccx, 0), tcx.types.bool], false)),
"load" => (1, vec![tcx.mk_imm_ptr(param(ccx, 0))],
param(ccx, 0)),
"store" => (1, vec![tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)],
"add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" =>
(1, vec![param(ccx, 0), param(ccx, 0)],
- tcx.intern_tup(&[param(ccx, 0), tcx.types.bool])),
+ tcx.intern_tup(&[param(ccx, 0), tcx.types.bool], false)),
"unchecked_div" | "unchecked_rem" =>
(1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
match *expected {
Void => match t.sty {
- ty::TyTuple(ref v) if v.is_empty() => {},
+ ty::TyTuple(ref v, _) if v.is_empty() => {},
_ => simple_error(&format!("`{}`", t), "()"),
},
// (The width we pass to LLVM doesn't concern the type checker.)
}
Aggregate(_flatten, ref expected_contents) => {
match t.sty {
- ty::TyTuple(contents) => {
+ ty::TyTuple(contents, _) => {
if contents.len() != expected_contents.len() {
simple_error(&format!("tuple with length {}", contents.len()),
&format!("tuple with length {}", expected_contents.len()));
self_ty, call_expr.id)?;
if let Some(import_id) = pick.import_id {
- self.tcx.used_trait_imports.borrow_mut().insert(import_id);
+ let import_def_id = self.tcx.hir.local_def_id(import_id);
+ debug!("used_trait_import: {:?}", import_def_id);
+ self.used_trait_imports.borrow_mut().insert(import_def_id);
}
self.tcx.check_stability(pick.item.def_id, call_expr.id, span);
self_ty, expr_id)?;
if let Some(import_id) = pick.import_id {
- self.tcx.used_trait_imports.borrow_mut().insert(import_id);
+ let import_def_id = self.tcx.hir.local_def_id(import_id);
+ debug!("used_trait_import: {:?}", import_def_id);
+ self.used_trait_imports.borrow_mut().insert(import_def_id);
}
let def = pick.item.def();
inherent_candidates: Vec<Candidate<'tcx>>,
extension_candidates: Vec<Candidate<'tcx>>,
impl_dups: FxHashSet<DefId>,
- import_id: Option<ast::NodeId>,
/// Collects near misses when the candidate functions are missing a `self` keyword and is only
/// used for error reporting
inherent_candidates: Vec::new(),
extension_candidates: Vec::new(),
impl_dups: FxHashSet(),
- import_id: None,
steps: Rc::new(steps),
opt_simplified_steps: opt_simplified_steps,
static_candidates: Vec::new(),
xform_self_ty: xform_self_ty,
item: item,
kind: InherentImplCandidate(impl_substs, obligations),
- import_id: self.import_id,
+ import_id: None,
});
}
}
xform_self_ty: xform_self_ty,
item: item,
kind: ObjectCandidate,
- import_id: this.import_id,
+ import_id: None,
});
});
}
xform_self_ty: xform_self_ty,
item: item,
kind: WhereClauseCandidate(poly_trait_ref),
- import_id: this.import_id,
+ import_id: None,
});
});
}
for trait_candidate in applicable_traits {
let trait_did = trait_candidate.def_id;
if duplicates.insert(trait_did) {
- self.import_id = trait_candidate.import_id;
- let result = self.assemble_extension_candidates_for_trait(trait_did);
- self.import_id = None;
+ let import_id = trait_candidate.import_id;
+ let result = self.assemble_extension_candidates_for_trait(import_id, trait_did);
result?;
}
}
let mut duplicates = FxHashSet();
for trait_info in suggest::all_traits(self.ccx) {
if duplicates.insert(trait_info.def_id) {
- self.assemble_extension_candidates_for_trait(trait_info.def_id)?;
+ self.assemble_extension_candidates_for_trait(None, trait_info.def_id)?;
}
}
Ok(())
}
fn assemble_extension_candidates_for_trait(&mut self,
+ import_id: Option<ast::NodeId>,
trait_def_id: DefId)
-> Result<(), MethodError<'tcx>> {
debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})",
continue;
}
- self.assemble_extension_candidates_for_trait_impls(trait_def_id, item.clone());
+ self.assemble_extension_candidates_for_trait_impls(import_id, trait_def_id,
+ item.clone());
- self.assemble_closure_candidates(trait_def_id, item.clone())?;
+ self.assemble_closure_candidates(import_id, trait_def_id, item.clone())?;
- self.assemble_projection_candidates(trait_def_id, item.clone());
+ self.assemble_projection_candidates(import_id, trait_def_id, item.clone());
- self.assemble_where_clause_candidates(trait_def_id, item.clone());
+ self.assemble_where_clause_candidates(import_id, trait_def_id, item.clone());
}
Ok(())
}
fn assemble_extension_candidates_for_trait_impls(&mut self,
+ import_id: Option<ast::NodeId>,
trait_def_id: DefId,
item: ty::AssociatedItem) {
let trait_def = self.tcx.lookup_trait_def(trait_def_id);
xform_self_ty: xform_self_ty,
item: item.clone(),
kind: ExtensionImplCandidate(impl_def_id, impl_substs, obligations),
- import_id: self.import_id,
+ import_id: import_id,
});
});
}
}
fn assemble_closure_candidates(&mut self,
+ import_id: Option<ast::NodeId>,
trait_def_id: DefId,
item: ty::AssociatedItem)
-> Result<(), MethodError<'tcx>> {
xform_self_ty: xform_self_ty,
item: item.clone(),
kind: TraitCandidate,
- import_id: self.import_id,
+ import_id: import_id,
});
}
}
fn assemble_projection_candidates(&mut self,
+ import_id: Option<ast::NodeId>,
trait_def_id: DefId,
item: ty::AssociatedItem) {
debug!("assemble_projection_candidates(\
xform_self_ty: xform_self_ty,
item: item.clone(),
kind: TraitCandidate,
- import_id: self.import_id,
+ import_id: import_id,
});
}
}
}
fn assemble_where_clause_candidates(&mut self,
+ import_id: Option<ast::NodeId>,
trait_def_id: DefId,
item: ty::AssociatedItem) {
debug!("assemble_where_clause_candidates(trait_def_id={:?})",
xform_self_ty: xform_self_ty,
item: item.clone(),
kind: WhereClauseCandidate(poly_bound),
- import_id: self.import_id,
+ import_id: import_id,
});
}
}
use TypeAndSubsts;
use lint;
use util::common::{ErrorReported, indenter};
-use util::nodemap::{DefIdMap, FxHashMap, FxHashSet, NodeMap};
+use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, FxHashSet, NodeMap};
use std::cell::{Cell, RefCell};
use std::cmp;
// Obligations which will have to be checked at the end of
// type-checking, after all functions have been inferred.
deferred_obligations: RefCell<Vec<traits::DeferredObligation<'tcx>>>,
+
+ // a set of trait import def-ids that we use during method
+ // resolution; during writeback, this is written into
+ // `tcx.used_trait_imports` for this item def-id
+ used_trait_imports: RefCell<FxHashSet<DefId>>,
}
impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> {
deferred_cast_checks: RefCell::new(Vec::new()),
anon_types: RefCell::new(DefIdMap()),
deferred_obligations: RefCell::new(Vec::new()),
+ used_trait_imports: RefCell::new(DefIdSet()),
}
}
fn re_infer(&self, span: Span, def: Option<&ty::RegionParameterDef>)
-> Option<&'tcx ty::Region> {
let v = match def {
- Some(def) => infer::EarlyBoundRegion(span, def.name),
+ Some(def) => infer::EarlyBoundRegion(span, def.name, def.issue_32330),
None => infer::MiscVariable(span)
};
Some(self.next_region_var(v))
if self.diverges.get() == Diverges::Always {
self.diverges.set(Diverges::WarnedAlways);
- self.tcx.sess.add_lint(lint::builtin::UNREACHABLE_CODE,
- id, span,
- format!("unreachable {}", kind));
+ self.tables.borrow_mut().lints.add_lint(
+ lint::builtin::UNREACHABLE_CODE,
+ id, span,
+ format!("unreachable {}", kind));
}
}
}
/// Apply "fallbacks" to some types
- /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
+ /// unconstrained types get replaced with ! or () (depending on whether
+ /// feature(never_type) is enabled), unconstrained ints with i32, and
+ /// unconstrained floats with f64.
fn default_type_parameters(&self) {
use rustc::ty::error::UnconstrainedNumeric::Neither;
use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
let err_inputs = match tuple_arguments {
DontTupleArguments => err_inputs,
- TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..])],
+ TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..], false)],
};
self.check_argument_types(sp, &err_inputs[..], &[], args_no_rcvr,
let formal_tys = if tuple_arguments == TupleArguments {
let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]);
match tuple_type.sty {
- ty::TyTuple(arg_types) if arg_types.len() != args.len() => {
+ ty::TyTuple(arg_types, _) if arg_types.len() != args.len() => {
parameter_count_error(tcx.sess, sp_args, arg_types.len(), args.len(),
"E0057", false, def_span);
expected_arg_tys = &[];
self.err_args(args.len())
}
- ty::TyTuple(arg_types) => {
+ ty::TyTuple(arg_types, _) => {
expected_arg_tys = match expected_arg_tys.get(0) {
Some(&ty) => match ty.sty {
- ty::TyTuple(ref tys) => &tys,
+ ty::TyTuple(ref tys, _) => &tys,
_ => &[]
},
None => &[]
}
})
}
- ty::TyTuple(ref v) => {
+ ty::TyTuple(ref v, _) => {
tuple_like = true;
v.get(idx.node).cloned()
}
hir::ExprTup(ref elts) => {
let flds = expected.only_has_type(self).and_then(|ty| {
match ty.sty {
- ty::TyTuple(ref flds) => Some(&flds[..]),
+ ty::TyTuple(ref flds, _) => Some(&flds[..]),
_ => None
}
});
};
t
});
- let tuple = tcx.mk_tup(elt_ts_iter);
+ let tuple = tcx.mk_tup(elt_ts_iter, false);
if tuple.references_error() {
tcx.types.err
} else {
},
base_t);
// Try to give some advice about indexing tuples.
- if let ty::TyTuple(_) = base_t.sty {
+ if let ty::TyTuple(..) = base_t.sty {
let mut needs_note = true;
// If the index is an integer, we can show the actual
// fixed expression:
use super::FnCtxt;
use hir::def_id::DefId;
use rustc::ty::{Ty, TypeFoldable, PreferMutLvalue, TypeVariants};
+use rustc::ty::TypeVariants::{TyStr, TyRef};
use rustc::infer::type_variable::TypeVariableOrigin;
+use errors;
use syntax::ast;
use syntax::symbol::Symbol;
use rustc::hir;
};
if let Some(missing_trait) = missing_trait {
- span_note!(&mut err, lhs_expr.span,
- "an implementation of `{}` might be missing for `{}`",
- missing_trait, lhs_ty);
+ if missing_trait == "std::ops::Add" &&
+ self.check_str_addition(expr, lhs_expr, lhs_ty,
+ rhs_expr, rhs_ty_var, &mut err) {
+ // This has nothing here because it means we did string
+ // concatenation (e.g. "Hello " + "World!"). This means
+ // we don't want the span in the else clause to be emmitted
+ } else {
+ span_note!(&mut err, lhs_expr.span,
+ "an implementation of `{}` might be missing for `{}`",
+ missing_trait, lhs_ty);
+ }
}
err.emit();
}
(rhs_ty_var, return_ty)
}
+ fn check_str_addition(&self,
+ expr: &'gcx hir::Expr,
+ lhs_expr: &'gcx hir::Expr,
+ lhs_ty: Ty<'tcx>,
+ rhs_expr: &'gcx hir::Expr,
+ rhs_ty_var: Ty<'tcx>,
+ mut err: &mut errors::DiagnosticBuilder) -> bool {
+ // If this function returns false it means we use it to make sure we print
+ // out the an "implementation of span_note!" above where this function is
+ // called and if true we don't.
+ let mut is_string_addition = false;
+ let rhs_ty = self.check_expr_coercable_to_type(rhs_expr, rhs_ty_var);
+ if let TyRef(_, l_ty) = lhs_ty.sty {
+ if let TyRef(_, r_ty) = rhs_ty.sty {
+ if l_ty.ty.sty == TyStr && r_ty.ty.sty == TyStr {
+ span_note!(&mut err, lhs_expr.span,
+ "`+` can't be used to concatenate two `&str` strings");
+ let codemap = self.tcx.sess.codemap();
+ let suggestion =
+ match (codemap.span_to_snippet(lhs_expr.span),
+ codemap.span_to_snippet(rhs_expr.span)) {
+ (Ok(lstring), Ok(rstring)) =>
+ format!("{}.to_owned() + {}", lstring, rstring),
+ _ => format!("<expression>")
+ };
+ err.span_suggestion(expr.span,
+ &format!("to_owned() can be used to create an owned `String` \
+ from a string reference. String concatenation \
+ appends the string on the right to the string \
+ on the left and may require reallocation. This \
+ requires ownership of the string on the left."), suggestion);
+ is_string_addition = true;
+ }
+
+ }
+
+ }
+
+ is_string_addition
+ }
+
pub fn check_user_unop(&self,
op_str: &str,
mname: &str,
use rustc::ty::adjustment;
use rustc::ty::fold::{TypeFolder,TypeFoldable};
use rustc::infer::{InferCtxt, FixupError};
-use rustc::util::nodemap::DefIdMap;
+use rustc::util::nodemap::{DefIdMap, DefIdSet};
use std::cell::Cell;
+use std::mem;
use syntax::ast;
use syntax_pos::Span;
wbcx.visit_deferred_obligations(item_id);
wbcx.visit_type_nodes();
wbcx.visit_cast_types();
+ wbcx.visit_lints();
let tables = self.tcx.alloc_tables(wbcx.tables);
self.tcx.tables.borrow_mut().insert(item_def_id, tables);
+
+ let used_trait_imports = mem::replace(&mut *self.used_trait_imports.borrow_mut(),
+ DefIdSet());
+ debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports);
+ self.tcx.used_trait_imports.borrow_mut().insert(item_def_id, used_trait_imports);
}
}
};
match *r {
ty::ReFree(ty::FreeRegion {
- bound_region: ty::BoundRegion::BrNamed(def_id, name, _), ..
+ bound_region: ty::BoundRegion::BrNamed(def_id, name), ..
}) => {
let bound_region = gcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
index: i as u32,
self.fcx.tables.borrow().cast_kinds.iter().map(|(&key, &value)| (key, value)));
}
+ fn visit_lints(&mut self) {
+ if self.fcx.writeback_errors.get() {
+ return
+ }
+
+ self.fcx.tables.borrow_mut().lints.transfer(&mut self.tables.lints);
+ }
+
fn visit_anon_types(&self) {
if self.fcx.writeback_errors.get() {
return
use rustc::hir;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::util::nodemap::DefIdSet;
-struct UnusedTraitImportVisitor<'a, 'tcx: 'a> {
+struct CheckVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ used_trait_imports: DefIdSet,
}
-impl<'a, 'tcx> UnusedTraitImportVisitor<'a, 'tcx> {
+impl<'a, 'tcx> CheckVisitor<'a, 'tcx> {
fn check_import(&self, id: ast::NodeId, span: Span) {
if !self.tcx.maybe_unused_trait_imports.contains(&id) {
return;
}
- if self.tcx.used_trait_imports.borrow().contains(&id) {
+
+ let import_def_id = self.tcx.hir.local_def_id(id);
+ if self.used_trait_imports.contains(&import_def_id) {
return;
}
}
}
-impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for UnusedTraitImportVisitor<'a, 'tcx> {
+impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CheckVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
if item.vis == hir::Public || item.span == DUMMY_SP {
return;
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let _task = tcx.dep_graph.in_task(DepNode::UnusedTraitCheck);
- let mut visitor = UnusedTraitImportVisitor { tcx: tcx };
+
+ let mut used_trait_imports = DefIdSet();
+ for &body_id in tcx.hir.krate().bodies.keys() {
+ let item_id = tcx.hir.body_owner(body_id);
+ let item_def_id = tcx.hir.local_def_id(item_id);
+
+ // this will have been written by the main typeck pass
+ if let Some(imports) = tcx.used_trait_imports.borrow().get(&item_def_id) {
+ debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
+ used_trait_imports.extend(imports);
+ } else {
+ debug!("GatherVisitor: item_def_id={:?} with no imports", item_def_id);
+ }
+ }
+
+ let mut visitor = CheckVisitor { tcx, used_trait_imports };
tcx.hir.krate().visit_all_item_likes(&mut visitor);
}
// done by the orphan and overlap modules. Then we build up various
// mappings. That mapping code resides here.
+use dep_graph::DepTrackingMap;
use hir::def_id::DefId;
-use rustc::ty::{self, TyCtxt, TypeFoldable};
+use rustc::ty::{self, maps, TyCtxt, TypeFoldable};
use rustc::ty::{Ty, TyBool, TyChar, TyError};
use rustc::ty::{TyParam, TyRawPtr};
use rustc::ty::{TyRef, TyAdt, TyDynamic, TyNever, TyTuple};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir::{Item, ItemImpl};
use rustc::hir;
+use std::cell::RefMut;
mod builtin;
mod orphan;
mod overlap;
mod unsafety;
-struct CoherenceChecker<'a, 'tcx: 'a> {
+struct CoherenceCollect<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ inherent_impls: RefMut<'a, DepTrackingMap<maps::InherentImpls<'tcx>>>,
}
-impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceChecker<'a, 'tcx> {
+impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCollect<'a, 'tcx> {
fn visit_item(&mut self, item: &Item) {
if let ItemImpl(..) = item.node {
self.check_implementation(item)
}
}
-impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
+impl<'a, 'tcx> CoherenceCollect<'a, 'tcx> {
+ fn check(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+ let inherent_impls = tcx.inherent_impls.borrow_mut();
+ let mut this = &mut CoherenceCollect { tcx, inherent_impls };
+
+ // Check implementations and traits. This populates the tables
+ // containing the inherent methods and extension methods. It also
+ // builds up the trait inheritance table.
+ tcx.visit_all_item_likes_in_krate(DepNode::CoherenceCheckImpl, this);
+ }
+
// Returns the def ID of the base type, if there is one.
fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
match ty.sty {
}
}
- fn check(&mut self) {
- // Check implementations and traits. This populates the tables
- // containing the inherent methods and extension methods. It also
- // builds up the trait inheritance table.
- self.tcx.visit_all_item_likes_in_krate(DepNode::CoherenceCheckImpl, self);
- }
-
- fn check_implementation(&self, item: &Item) {
+ fn check_implementation(&mut self, item: &Item) {
let tcx = self.tcx;
let impl_did = tcx.hir.local_def_id(item.id);
let self_type = tcx.item_type(impl_did);
}
}
- fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
- self.tcx.inherent_impls.borrow_mut().push(base_def_id, impl_def_id);
+ fn add_inherent_impl(&mut self, base_def_id: DefId, impl_def_id: DefId) {
+ // Subtle: it'd be better to collect these into a local map
+ // and then write the vector only once all items are known,
+ // but that leads to degenerate dep-graphs. The problem is
+ // that the write of that big vector winds up having reads
+ // from *all* impls in the krate, since we've lost the
+ // precision basically. This would be ok in the firewall
+ // model so once we've made progess towards that we can modify
+ // the strategy here. In the meantime, using `push` is ok
+ // because we are doing this as a pre-pass before anyone
+ // actually reads from `inherent_impls` -- and we know this is
+ // true beacuse we hold the refcell lock.
+ self.inherent_impls.push(base_def_id, impl_def_id);
}
fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'tcx>, impl_def_id: DefId) {
}
pub fn check_coherence(ccx: &CrateCtxt) {
+ CoherenceCollect::check(ccx.tcx);
+
let _task = ccx.tcx.dep_graph.in_task(DepNode::Coherence);
- CoherenceChecker { tcx: ccx.tcx }.check();
unsafety::check(ccx.tcx);
orphan::check(ccx.tcx);
overlap::check(ccx.tcx);
ccx.tcx.item_types.borrow_mut().insert(ty_f.did, tt);
let def_id = ccx.tcx.hir.local_def_id(field.id);
- ccx.tcx.item_types.borrow_mut().insert(def_id, tt);
+ assert_eq!(def_id, ty_f.did);
ccx.tcx.generics.borrow_mut().insert(def_id, struct_generics);
ccx.tcx.predicates.borrow_mut().insert(def_id, struct_predicates.clone());
}
let const_def_id = ccx.tcx.hir.local_def_id(trait_item.id);
generics_of_def_id(ccx, const_def_id);
let ty = ccx.icx(&trait_predicates).to_ty(&ty);
- tcx.item_types.borrow_mut().insert(const_def_id, ty);
- convert_associated_const(ccx, TraitContainer(trait_def_id),
- trait_item.id, ty);
+ convert_associated_const(ccx,
+ TraitContainer(trait_def_id),
+ trait_item.id,
+ ty);
}
hir::TraitItemKind::Type(_, ref opt_ty) => {
let const_def_id = ccx.tcx.hir.local_def_id(impl_item.id);
generics_of_def_id(ccx, const_def_id);
let ty = ccx.icx(&impl_predicates).to_ty(&ty);
- tcx.item_types.borrow_mut().insert(const_def_id, ty);
- convert_associated_const(ccx, ImplContainer(impl_def_id),
- impl_item.id, ty);
+ convert_associated_const(ccx,
+ ImplContainer(impl_def_id),
+ impl_item.id,
+ ty);
}
hir::ImplItemKind::Type(ref ty) => {
items);
trait_predicates.predicates.extend(assoc_predicates);
- let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates);
- assert!(prev_predicates.is_none());
-
+ tcx.predicates.borrow_mut().insert(def_id, trait_predicates);
return;
fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics);
let regions = early_lifetimes.iter().enumerate().map(|(i, l)| {
+ let issue_32330 = ccx.tcx.named_region_map.issue_32330
+ .get(&l.lifetime.id)
+ .cloned();
ty::RegionParameterDef {
name: l.lifetime.name,
index: own_start + i as u32,
def_id: tcx.hir.local_def_id(l.lifetime.id),
pure_wrt_drop: l.pure_wrt_drop,
+ issue_32330: issue_32330,
}
}).collect::<Vec<_>>();
};
let predicates = ty_generic_predicates(ccx, generics, None, vec![], false);
- let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id,
- predicates.clone());
- assert!(prev_predicates.is_none());
+ ccx.tcx.predicates.borrow_mut().insert(def_id, predicates.clone());
predicates
}
};
let predicates = ty_generic_predicates(ccx, generics, None, vec![], false);
- let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, predicates);
- assert!(prev_predicates.is_none());
+ ccx.tcx.predicates.borrow_mut().insert(def_id, predicates);
}
// Is it marked with ?Sized
ast_generics
.lifetimes
.iter()
- .filter(|l| !ccx.tcx.named_region_map.late_bound.contains_key(&l.lifetime.id))
+ .filter(|l| !ccx.tcx.named_region_map.late_bound.contains(&l.lifetime.id))
.collect()
}
```
"##,
+E0581: r##"
+In a `fn` type, a lifetime appears only in the return type,
+and not in the arguments types.
+
+Erroneous code example:
+
+```compile_fail,E0581
+fn main() {
+ // Here, `'a` appears only in the return type:
+ let x: for<'a> fn() -> &'a i32;
+}
+```
+
+To fix this issue, either use the lifetime in the arguments, or use
+`'static`. Example:
+
+```
+fn main() {
+ // Here, `'a` appears only in the return type:
+ let x: for<'a> fn(&'a i32) -> &'a i32;
+ let y: fn() -> &'static i32;
+}
+```
+
+Note: The examples above used to be (erroneously) accepted by the
+compiler, but this was since corrected. See [issue #33685] for more
+details.
+
+[issue #33685]: https://github.com/rust-lang/rust/issues/33685
+"##,
+
+ E0582: r##"
+A lifetime appears only in an associated-type binding,
+and not in the input types to the trait.
+
+Erroneous code example:
+
+```compile_fail,E0582
+fn bar<F>(t: F)
+ // No type can satisfy this requirement, since `'a` does not
+ // appear in any of the input types (here, `i32`):
+ where F: for<'a> Fn(i32) -> Option<&'a i32>
+{
+}
+
+fn main() { }
+```
+
+To fix this issue, either use the lifetime in the inputs, or use
+`'static`. Example:
+
+```
+fn bar<F, G>(t: F, u: G)
+ where F: for<'a> Fn(&'a i32) -> Option<&'a i32>,
+ G: Fn(i32) -> Option<&'static i32>,
+{
+}
+
+fn main() { }
+```
+
+Note: The examples above used to be (erroneously) accepted by the
+compiler, but this was since corrected. See [issue #33685] for more
+details.
+
+[issue #33685]: https://github.com/rust-lang/rust/issues/33685
+"##,
+
}
register_diagnostics! {
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(conservative_impl_trait)]
+#![feature(field_init_shorthand)]
#![feature(loop_break_value)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
self.add_constraints_from_mt(generics, mt, variance);
}
- ty::TyTuple(subtys) => {
+ ty::TyTuple(subtys, _) => {
for &subty in subtys {
self.add_constraints_from_ty(generics, subty, variance);
}
item_variances);
}
- let newly_added = tcx.item_variance_map
- .borrow_mut()
- .insert(item_def_id, Rc::new(item_variances))
- .is_none();
- assert!(newly_added);
+ tcx.item_variance_map
+ .borrow_mut()
+ .insert(item_def_id, Rc::new(item_variances));
}
}
// parameters".
if self.num_inferred() == inferreds_on_entry {
let item_def_id = self.tcx.hir.local_def_id(item_id);
- let newly_added = self.tcx
+ self.tcx
.item_variance_map
.borrow_mut()
- .insert(item_def_id, self.empty_variances.clone())
- .is_none();
- assert!(newly_added);
+ .insert(item_def_id, self.empty_variances.clone());
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug, Default)]
pub struct Attributes {
pub doc_strings: Vec<String>,
- pub other_attrs: Vec<ast::Attribute>
+ pub other_attrs: Vec<ast::Attribute>,
+ pub span: Option<syntax_pos::Span>,
}
impl Attributes {
pub fn from_ast(attrs: &[ast::Attribute]) -> Attributes {
let mut doc_strings = vec![];
+ let mut sp = None;
let other_attrs = attrs.iter().filter_map(|attr| {
attr.with_desugared_doc(|attr| {
if let Some(value) = attr.value_str() {
if attr.check_name("doc") {
doc_strings.push(value.to_string());
+ if sp.is_none() {
+ sp = Some(attr.span);
+ }
return None;
}
}
}).collect();
Attributes {
doc_strings: doc_strings,
- other_attrs: other_attrs
+ other_attrs: other_attrs,
+ span: sp,
}
}
Some(did) if cx.tcx.lang_items.fn_trait_kind(did).is_some() => {
assert_eq!(types.len(), 1);
let inputs = match types[0].sty {
- ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
+ ty::TyTuple(ref tys, _) => tys.iter().map(|t| t.clean(cx)).collect(),
_ => {
return PathParameters::AngleBracketed {
lifetimes: lifetimes,
let output = None;
// FIXME(#20299) return type comes from a projection now
// match types[1].sty {
- // ty::TyTuple(ref v) if v.is_empty() => None, // -> ()
+ // ty::TyTuple(ref v, _) if v.is_empty() => None, // -> ()
// _ => Some(types[1].clean(cx))
// };
PathParameters::Parenthesized {
// collect any late bound regions
let mut late_bounds = vec![];
for ty_s in self.input_types().skip(1) {
- if let ty::TyTuple(ts) = ty_s.sty {
+ if let ty::TyTuple(ts, _) = ty_s.sty {
for &ty_s in ts {
if let ty::TyRef(ref reg, _) = ty_s.sty {
if let &ty::Region::ReLateBound(..) = *reg {
fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
match *self {
ty::ReStatic => Some(Lifetime::statik()),
- ty::ReLateBound(_, ty::BrNamed(_, name, _)) => Some(Lifetime(name.to_string())),
+ ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name.to_string())),
ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
ty::ReLateBound(..) |
Never
}
}
- ty::TyTuple(ref t) => Tuple(t.clean(cx)),
+ ty::TyTuple(ref t, _) => Tuple(t.clean(cx)),
ty::TyProjection(ref data) => data.clean(cx),
enum hoedown_document {}
type blockcodefn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
- *const hoedown_buffer, *const hoedown_renderer_data);
+ *const hoedown_buffer, *const hoedown_renderer_data,
+ libc::size_t);
type blockquotefn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
- *const hoedown_renderer_data);
+ *const hoedown_renderer_data, libc::size_t);
type headerfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
- libc::c_int, *const hoedown_renderer_data);
+ libc::c_int, *const hoedown_renderer_data,
+ libc::size_t);
type blockhtmlfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
- *const hoedown_renderer_data);
+ *const hoedown_renderer_data, libc::size_t);
type codespanfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
- *const hoedown_renderer_data) -> libc::c_int;
+ *const hoedown_renderer_data, libc::size_t) -> libc::c_int;
type linkfn = extern "C" fn (*mut hoedown_buffer, *const hoedown_buffer,
*const hoedown_buffer, *const hoedown_buffer,
- *const hoedown_renderer_data) -> libc::c_int;
+ *const hoedown_renderer_data, libc::size_t) -> libc::c_int;
type entityfn = extern "C" fn (*mut hoedown_buffer, *const hoedown_buffer,
- *const hoedown_renderer_data);
+ *const hoedown_renderer_data, libc::size_t);
type normaltextfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
- *const hoedown_renderer_data);
+ *const hoedown_renderer_data, libc::size_t);
#[repr(C)]
struct hoedown_renderer_data {
struct MyOpaque {
dfltblk: extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
- *const hoedown_buffer, *const hoedown_renderer_data),
+ *const hoedown_buffer, *const hoedown_renderer_data,
+ libc::size_t),
toc_builder: Option<TocBuilder>,
}
print_toc: bool,
html_flags: libc::c_uint) -> fmt::Result {
extern fn block(ob: *mut hoedown_buffer, orig_text: *const hoedown_buffer,
- lang: *const hoedown_buffer, data: *const hoedown_renderer_data) {
+ lang: *const hoedown_buffer, data: *const hoedown_renderer_data,
+ line: libc::size_t) {
unsafe {
if orig_text.is_null() { return }
let rlang = str::from_utf8(rlang).unwrap();
if !LangString::parse(rlang).rust {
(my_opaque.dfltblk)(ob, orig_text, lang,
- opaque as *const hoedown_renderer_data);
+ opaque as *const hoedown_renderer_data,
+ line);
true
} else {
false
}
extern fn header(ob: *mut hoedown_buffer, text: *const hoedown_buffer,
- level: libc::c_int, data: *const hoedown_renderer_data) {
+ level: libc::c_int, data: *const hoedown_renderer_data,
+ _: libc::size_t) {
// hoedown does this, we may as well too
unsafe { hoedown_buffer_puts(ob, "\n\0".as_ptr() as *const _); }
ob: *mut hoedown_buffer,
text: *const hoedown_buffer,
_: *const hoedown_renderer_data,
+ _: libc::size_t
) -> libc::c_int {
let content = if text.is_null() {
"".to_owned()
}
}
-pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) {
+pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, start_line: usize) {
extern fn block(_ob: *mut hoedown_buffer,
text: *const hoedown_buffer,
lang: *const hoedown_buffer,
- data: *const hoedown_renderer_data) {
+ data: *const hoedown_renderer_data,
+ line: libc::size_t) {
unsafe {
if text.is_null() { return }
let block_info = if lang.is_null() {
stripped_filtered_line(l).unwrap_or(l)
});
let text = lines.collect::<Vec<&str>>().join("\n");
+ let line = tests.get_line() + line;
tests.add_test(text.to_owned(),
block_info.should_panic, block_info.no_run,
block_info.ignore, block_info.test_harness,
- block_info.compile_fail, block_info.error_codes);
+ block_info.compile_fail, block_info.error_codes,
+ line);
}
}
extern fn header(_ob: *mut hoedown_buffer,
text: *const hoedown_buffer,
- level: libc::c_int, data: *const hoedown_renderer_data) {
+ level: libc::c_int, data: *const hoedown_renderer_data,
+ _: libc::size_t) {
unsafe {
let opaque = (*data).opaque as *mut hoedown_html_renderer_state;
let tests = &mut *((*opaque).opaque as *mut ::test::Collector);
}
}
+ tests.set_line(start_line);
unsafe {
let ob = hoedown_buffer_new(DEF_OUNIT);
let renderer = hoedown_html_renderer_new(0, 0);
#[derive(Eq, PartialEq, Clone, Debug)]
struct LangString {
+ original: String,
should_panic: bool,
no_run: bool,
ignore: bool,
impl LangString {
fn all_false() -> LangString {
LangString {
+ original: String::new(),
should_panic: false,
no_run: false,
ignore: false,
allow_error_code_check = true;
}
+ data.original = string.to_owned();
let tokens = string.split(|c: char|
!(c == '_' || c == '-' || c.is_alphanumeric())
);
_link: *const hoedown_buffer,
_title: *const hoedown_buffer,
content: *const hoedown_buffer,
- data: *const hoedown_renderer_data) -> libc::c_int
+ data: *const hoedown_renderer_data,
+ _: libc::size_t) -> libc::c_int
{
unsafe {
if !content.is_null() && (*content).size > 0 {
}
extern fn normal_text(_ob: *mut hoedown_buffer,
- text: *const hoedown_buffer,
- data: *const hoedown_renderer_data)
+ text: *const hoedown_buffer,
+ data: *const hoedown_renderer_data,
+ _: libc::size_t)
{
unsafe {
let ob = (*data).opaque as *mut hoedown_buffer;
test_harness: test_harness,
compile_fail: compile_fail,
error_codes: error_codes,
+ original: s.to_owned(),
})
}
t("no_run", false, true, false, true, false, false, Vec::new());
t("test_harness", false, false, false, true, true, false, Vec::new());
t("compile_fail", false, true, false, true, false, true, Vec::new());
- t("E0450", false, false, false, true, false, false,
- vec!["E0450".to_owned()]);
t("{.no_run .example}", false, true, false, true, false, false, Vec::new());
t("{.sh .should_panic}", true, false, false, true, false, false, Vec::new());
t("{.example .rust}", false, false, false, true, false, false, Vec::new());
String::new()
};
- let mut unsafety_flag = "";
- if let clean::FunctionItem(ref func) = myitem.inner {
- if func.unsafety == hir::Unsafety::Unsafe {
- unsafety_flag = "<a title='unsafe function' href='#'><sup>âš </sup></a>";
+ let unsafety_flag = match myitem.inner {
+ clean::FunctionItem(ref func) | clean::ForeignFunctionItem(ref func)
+ if func.unsafety == hir::Unsafety::Unsafe => {
+ "<a title='unsafe function' href='#'><sup>âš </sup></a>"
}
- }
+ _ => "",
+ };
let doc_value = myitem.doc_value().unwrap_or("");
write!(w, "
nightly_options::check_nightly_options(&matches, &opts());
if matches.opt_present("h") || matches.opt_present("help") {
- usage(&args[0]);
+ usage("rustdoc");
return 0;
} else if matches.opt_present("version") {
rustc_driver::version("rustdoc", &matches);
let mut opts = TestOptions::default();
opts.no_crate_inject = true;
let mut collector = Collector::new(input.to_string(), cfgs, libs, externs,
- true, opts, maybe_sysroot);
- find_testable_code(&input_str, &mut collector);
+ true, opts, maybe_sysroot, "input".to_string(),
+ None);
+ find_testable_code(&input_str, &mut collector, 0);
test_args.insert(0, "rustdoctest".to_string());
testing::test_main(&test_args, collector.tests);
0
use syntax::ast;
use syntax::codemap::CodeMap;
use syntax::feature_gate::UnstableFeatures;
+use syntax_pos::{BytePos, DUMMY_SP, Pos};
use errors;
use errors::emitter::ColorConfig;
let _ignore = dep_graph.in_ignore();
let cstore = Rc::new(CStore::new(&dep_graph));
let mut sess = session::build_session_(
- sessopts, &dep_graph, Some(input_path.clone()), handler, codemap, cstore.clone(),
+ sessopts, &dep_graph, Some(input_path.clone()), handler, codemap.clone(), cstore.clone(),
);
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
sess.parse_sess.config =
link::find_crate_name(None, &hir_forest.krate().attrs, &input)
});
let opts = scrape_test_config(hir_forest.krate());
+ let filename = input_path.to_str().unwrap_or("").to_owned();
let mut collector = Collector::new(crate_name,
cfgs,
libs,
externs,
false,
opts,
- maybe_sysroot);
+ maybe_sysroot,
+ filename,
+ Some(codemap));
{
let dep_graph = DepGraph::new(false);
error_codes.retain(|err| !out.contains(err));
}
}
- Ok(()) if compile_fail => panic!("test compiled while it wasn't supposed to"),
+ Ok(()) if compile_fail => {
+ panic!("test compiled while it wasn't supposed to")
+ }
_ => {}
}
}
if should_panic && out.status.success() {
panic!("test executable succeeded when it should have failed");
} else if !should_panic && !out.status.success() {
- panic!("test executable failed:\n{}\n{}",
+ panic!("test executable failed:\n{}\n{}\n",
str::from_utf8(&out.stdout).unwrap_or(""),
str::from_utf8(&out.stderr).unwrap_or(""));
}
prog
}
+// FIXME(aburka): use a real parser to deal with multiline attributes
fn partition_source(s: &str) -> (String, String) {
use std_unicode::str::UnicodeStr;
for line in s.lines() {
let trimline = line.trim();
let header = trimline.is_whitespace() ||
- trimline.starts_with("#![feature");
+ trimline.starts_with("#![");
if !header || after_header {
after_header = true;
after.push_str(line);
cratename: String,
opts: TestOptions,
maybe_sysroot: Option<PathBuf>,
+ filename: String,
+ start_line: usize,
+ codemap: Option<Rc<CodeMap>>,
}
impl Collector {
pub fn new(cratename: String, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
- use_headers: bool, opts: TestOptions, maybe_sysroot: Option<PathBuf>) -> Collector {
+ use_headers: bool, opts: TestOptions, maybe_sysroot: Option<PathBuf>,
+ filename: String, codemap: Option<Rc<CodeMap>>) -> Collector {
Collector {
tests: Vec::new(),
names: Vec::new(),
cratename: cratename,
opts: opts,
maybe_sysroot: maybe_sysroot,
+ filename: filename,
+ start_line: 0,
+ codemap: codemap,
}
}
pub fn add_test(&mut self, test: String,
should_panic: bool, no_run: bool, should_ignore: bool,
- as_test_harness: bool, compile_fail: bool, error_codes: Vec<String>) {
- let name = if self.use_headers {
- let s = self.current_header.as_ref().map(|s| &**s).unwrap_or("");
- format!("{}_{}", s, self.cnt)
- } else {
- format!("{}_{}", self.names.join("::"), self.cnt)
- };
+ as_test_harness: bool, compile_fail: bool, error_codes: Vec<String>,
+ line: usize) {
+ let name = format!("{} - line {}", self.filename, line);
self.cnt += 1;
let cfgs = self.cfgs.clone();
let libs = self.libs.clone();
});
}
+ pub fn get_line(&self) -> usize {
+ if let Some(ref codemap) = self.codemap{
+ let line = codemap.lookup_char_pos(BytePos(self.start_line as u32)).line;
+ if line > 0 { line - 1 } else { line }
+ } else {
+ self.start_line
+ }
+ }
+
+ pub fn set_line(&mut self, start_line: usize) {
+ self.start_line = start_line;
+ }
+
pub fn register_header(&mut self, name: &str, level: u32) {
if self.use_headers && level == 1 {
// we use these headings as test names, so it's good if
attrs.unindent_doc_comments();
if let Some(doc) = attrs.doc_value() {
self.collector.cnt = 0;
- markdown::find_testable_code(doc, self.collector);
+ markdown::find_testable_code(doc, self.collector,
+ attrs.span.unwrap_or(DUMMY_SP).lo.to_usize());
}
nested(self);
name = "serialize"
path = "lib.rs"
crate-type = ["dylib", "rlib"]
-
-[dependencies]
-rustc_i128 = { path = "../librustc_i128" }
use std::{char, f64, fmt, str};
use std;
-use rustc_i128::{i128, u128};
-
use Encodable;
/// Represents a json value
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use rustc_i128::{i128, u128};
-
#[inline]
fn write_to_vec(vec: &mut Vec<u8>, position: usize, byte: u8) {
if position == vec.len() {
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core_intrinsics)]
+#![feature(i128_type)]
#![feature(specialization)]
#![feature(staged_api)]
#![cfg_attr(test, feature(test))]
extern crate collections;
-extern crate rustc_i128;
-
pub use self::serialize::{Decoder, Encoder, Decodable, Encodable};
pub use self::serialize::{SpecializationError, SpecializedEncoder, SpecializedDecoder};
use std::io::{self, Write};
use serialize;
-use rustc_i128::{i128, u128};
-
// -----------------------------------------------------------------------------
// Encoder
// -----------------------------------------------------------------------------
use std::rc::Rc;
use std::cell::{Cell, RefCell};
use std::sync::Arc;
-use rustc_i128::{i128, u128};
pub trait Encoder {
type Error;
}
}
-#[cfg(not(stage0))]
impl Encodable for u128 {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_u128(*self)
}
}
-#[cfg(not(stage0))]
impl Decodable for u128 {
fn decode<D: Decoder>(d: &mut D) -> Result<u128, D::Error> {
d.read_u128()
}
}
-#[cfg(not(stage0))]
impl Encodable for i128 {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_i128(*self)
}
}
-#[cfg(not(stage0))]
impl Decodable for i128 {
fn decode<D: Decoder>(d: &mut D) -> Result<i128, D::Error> {
d.read_i128()
#[unstable(feature = "fused", issue = "35602")]
impl FusedIterator for EscapeDefault {}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for EscapeDefault {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("EscapeDefault { .. }")
#![deny(warnings)]
-extern crate gcc;
+#[macro_use]
extern crate build_helper;
+extern crate gcc;
use std::env;
-use std::path::PathBuf;
+use std::fs::{self, File};
+use std::path::{Path, PathBuf};
use std::process::Command;
-
-use build_helper::run;
+use build_helper::{run, rerun_if_changed_anything_in_dir, up_to_date};
fn main() {
println!("cargo:rustc-cfg=cargobuild");
}
fn build_libbacktrace(host: &str, target: &str) {
- let src_dir = env::current_dir().unwrap().join("../libbacktrace");
- let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
+ let build_dir = env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or(env::var_os("OUT_DIR").unwrap());
+ let build_dir = PathBuf::from(build_dir).join("libbacktrace");
+ let _ = fs::create_dir_all(&build_dir);
println!("cargo:rustc-link-lib=static=backtrace");
println!("cargo:rustc-link-search=native={}/.libs", build_dir.display());
-
- let mut stack = src_dir.read_dir().unwrap()
- .map(|e| e.unwrap())
- .collect::<Vec<_>>();
- while let Some(entry) = stack.pop() {
- let path = entry.path();
- if entry.file_type().unwrap().is_dir() {
- stack.extend(path.read_dir().unwrap().map(|e| e.unwrap()));
- } else {
- println!("cargo:rerun-if-changed={}", path.display());
- }
+ let src_dir = env::current_dir().unwrap().join("../libbacktrace");
+ rerun_if_changed_anything_in_dir(&src_dir);
+ let timestamp = build_dir.join("rustbuild.timestamp");
+ if up_to_date(&Path::new("build.rs"), ×tamp) && up_to_date(&src_dir, ×tamp) {
+ return
}
let compiler = gcc::Config::new().get_compiler();
.env("AR", &ar)
.env("RANLIB", format!("{} s", ar.display()))
.env("CFLAGS", cflags));
+
run(Command::new(build_helper::make(host))
.current_dir(&build_dir)
.arg(format!("INCDIR={}", src_dir.display()))
.arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")));
+
+ t!(File::create(×tamp));
}
/// attacks such as HashDoS.
///
/// The hashing algorithm can be replaced on a per-`HashMap` basis using the
-/// `HashMap::default`, `HashMap::with_hasher`, and
-/// `HashMap::with_capacity_and_hasher` methods. Many alternative algorithms
-/// are available on crates.io, such as the `fnv` crate.
+/// [`HashMap::default`], [`HashMap::with_hasher`], and
+/// [`HashMap::with_capacity_and_hasher`] methods. Many alternative algorithms
+/// are available on crates.io, such as the [`fnv`] crate.
///
/// It is required that the keys implement the [`Eq`] and [`Hash`] traits, although
/// this can frequently be achieved by using `#[derive(PartialEq, Eq, Hash)]`.
/// [`PartialEq`]: ../../std/cmp/trait.PartialEq.html
/// [`RefCell`]: ../../std/cell/struct.RefCell.html
/// [`Cell`]: ../../std/cell/struct.Cell.html
+/// [`HashMap::default`]: #method.default
+/// [`HashMap::with_hasher`]: #method.with_hasher
+/// [`HashMap::with_capacity_and_hasher`]: #method.with_capacity_and_hasher
+/// [`fnv`]: https://crates.io/crates/fnv
///
/// ```
/// use std::collections::HashMap;
///
/// # Panics
///
- /// Panics if the new allocation size overflows `usize`.
+ /// Panics if the new allocation size overflows [`usize`].
+ ///
+ /// [`usize`]: ../../std/primitive.usize.html
///
/// # Examples
///
/// Inserts a key-value pair into the map.
///
- /// If the map did not have this key present, `None` is returned.
+ /// If the map did not have this key present, [`None`] is returned.
///
/// If the map did have this key present, the value is updated, and the old
/// value is returned. The key is not updated, though; this matters for
/// types that can be `==` without being identical. See the [module-level
/// documentation] for more.
///
+ /// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [module-level documentation]: index.html#insert-and-complex-keys
///
/// # Examples
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, K: Debug, V: Debug> fmt::Debug for Iter<'a, K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list()
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, K: Debug, V: Debug> fmt::Debug for Keys<'a, K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list()
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, K: Debug, V: Debug> fmt::Debug for Values<'a, K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list()
#[unstable(feature = "fused", issue = "35602")]
impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, K, V> fmt::Debug for IterMut<'a, K, V>
where K: fmt::Debug,
V: fmt::Debug,
#[unstable(feature = "fused", issue = "35602")]
impl<K, V> FusedIterator for IntoIter<K, V> {}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<K: Debug, V: Debug> fmt::Debug for IntoIter<K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list()
#[unstable(feature = "fused", issue = "35602")]
impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, K, V> fmt::Debug for ValuesMut<'a, K, V>
where K: fmt::Debug,
V: fmt::Debug,
#[unstable(feature = "fused", issue = "35602")]
impl<'a, K, V> FusedIterator for Drain<'a, K, V> {}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, K, V> fmt::Debug for Drain<'a, K, V>
where K: fmt::Debug,
V: fmt::Debug,
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for RandomState {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("RandomState { .. }")
#[unstable(feature = "fused", issue = "35602")]
impl<'a, K> FusedIterator for Iter<'a, K> {}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, K: fmt::Debug> fmt::Debug for Iter<'a, K> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list()
#[unstable(feature = "fused", issue = "35602")]
impl<K> FusedIterator for IntoIter<K> {}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<K: fmt::Debug> fmt::Debug for IntoIter<K> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let entries_iter = self.iter.inner.iter().map(|(k, _)| k);
#[unstable(feature = "fused", issue = "35602")]
impl<'a, K> FusedIterator for Drain<'a, K> {}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, K: fmt::Debug> fmt::Debug for Drain<'a, K> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let entries_iter = self.iter.inner.iter().map(|(k, _)| k);
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, T, S> fmt::Debug for Intersection<'a, T, S>
where T: fmt::Debug + Eq + Hash,
S: BuildHasher,
{
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, T, S> fmt::Debug for Difference<'a, T, S>
where T: fmt::Debug + Eq + Hash,
S: BuildHasher,
{
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, T, S> fmt::Debug for SymmetricDifference<'a, T, S>
where T: fmt::Debug + Eq + Hash,
S: BuildHasher,
{
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, T, S> fmt::Debug for Union<'a, T, S>
where T: fmt::Debug + Eq + Hash,
S: BuildHasher,
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Vars {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("Vars { .. }")
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for VarsOs {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("VarsOs { .. }")
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a> fmt::Debug for SplitPaths<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("SplitPaths { .. }")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Args {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("Args { .. }")
fn next_back(&mut self) -> Option<OsString> { self.inner.next_back() }
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for ArgsOs {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("ArgsOs { .. }")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Metadata {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Metadata")
done_first: bool,
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<T: fmt::Debug, U: fmt::Debug> fmt::Debug for Chain<T, U> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Chain")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Stdin {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("Stdin { .. }")
fn consume(&mut self, n: usize) { self.inner.consume(n) }
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a> fmt::Debug for StdinLock<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("StdinLock { .. }")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Stdout {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("Stdout { .. }")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a> fmt::Debug for StdoutLock<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("StdoutLock { .. }")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Stderr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("Stderr { .. }")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a> fmt::Debug for StderrLock<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("StderrLock { .. }")
fn consume(&mut self, _n: usize) {}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Empty {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("Empty { .. }")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Repeat {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("Repeat { .. }")
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Sink {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("Sink { .. }")
#![feature(generic_param_attrs)]
#![feature(hashmap_hasher)]
#![feature(heap_api)]
+#![feature(i128)]
+#![feature(i128_type)]
#![feature(inclusive_range)]
#![feature(int_error_internals)]
#![feature(integer_atomics)]
#![feature(oom)]
#![feature(optin_builtin_traits)]
#![feature(panic_unwind)]
+#![feature(peek)]
#![feature(placement_in_syntax)]
#![feature(prelude_import)]
#![feature(pub_restricted)]
#![feature(unwind_attributes)]
#![feature(vec_push_all)]
#![feature(zero_one)]
-#![feature(i128)]
#![cfg_attr(test, feature(update_panic_count))]
// Explicitly import the prelude. The compiler uses this same unstable attribute
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::i64;
#[unstable(feature = "i128", issue = "35118")]
-#[cfg(not(stage0))]
pub use core::i128;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::usize;
#[stable(feature = "rust1", since = "1.0.0")]
pub use std_unicode::char;
#[unstable(feature = "i128", issue = "35118")]
-#[cfg(not(stage0))]
pub use core::u128;
pub mod f32;
}
}
+#[stable(feature = "addr_from_into_ip", since = "1.17.0")]
+impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr {
+ fn from(pieces: (I, u16)) -> SocketAddr {
+ SocketAddr::new(pieces.0.into(), pieces.1)
+ }
+}
+
impl<'a> IntoInner<(*const c::sockaddr, c::socklen_t)> for &'a SocketAddr {
fn into_inner(self) -> (*const c::sockaddr, c::socklen_t) {
match *self {
}
}
+#[stable(feature = "ip_from_slice", since = "1.17.0")]
+impl From<[u8; 4]> for IpAddr {
+ fn from(octets: [u8; 4]) -> IpAddr {
+ IpAddr::V4(Ipv4Addr::from(octets))
+ }
+}
+
impl Ipv6Addr {
/// Creates a new IPv6 address from eight 16-bit segments.
///
}
}
+#[unstable(feature = "i128", issue = "35118")]
+impl From<Ipv6Addr> for u128 {
+ fn from(ip: Ipv6Addr) -> u128 {
+ let ip = ip.segments();
+ ((ip[0] as u128) << 112) + ((ip[1] as u128) << 96) + ((ip[2] as u128) << 80) +
+ ((ip[3] as u128) << 64) + ((ip[4] as u128) << 48) + ((ip[5] as u128) << 32) +
+ ((ip[6] as u128) << 16) + (ip[7] as u128)
+ }
+}
+#[unstable(feature = "i128", issue = "35118")]
+impl From<u128> for Ipv6Addr {
+ fn from(ip: u128) -> Ipv6Addr {
+ Ipv6Addr::new(
+ (ip >> 112) as u16, (ip >> 96) as u16, (ip >> 80) as u16,
+ (ip >> 64) as u16, (ip >> 48) as u16, (ip >> 32) as u16,
+ (ip >> 16) as u16, ip as u16,
+ )
+ }
+}
+
#[stable(feature = "ipv6_from_octets", since = "1.9.0")]
impl From<[u8; 16]> for Ipv6Addr {
fn from(octets: [u8; 16]) -> Ipv6Addr {
}
}
+
+#[stable(feature = "ip_from_slice", since = "1.17.0")]
+impl From<[u8; 16]> for IpAddr {
+ fn from(octets: [u8; 16]) -> IpAddr {
+ IpAddr::V6(Ipv6Addr::from(octets))
+ }
+}
+
+#[stable(feature = "ip_from_slice", since = "1.17.0")]
+impl From<[u16; 8]> for IpAddr {
+ fn from(segments: [u16; 8]) -> IpAddr {
+ IpAddr::V6(Ipv6Addr::from(segments))
+ }
+}
+
// Tests for this module
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
#[test]
fn test_ipv4_to_int() {
- let a = Ipv4Addr::new(127, 0, 0, 1);
- assert_eq!(u32::from(a), 2130706433);
+ let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
+ assert_eq!(u32::from(a), 0x11223344);
}
#[test]
fn test_int_to_ipv4() {
- let a = Ipv4Addr::new(127, 0, 0, 1);
- assert_eq!(Ipv4Addr::from(2130706433), a);
+ let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
+ assert_eq!(Ipv4Addr::from(0x11223344), a);
+ }
+
+ #[test]
+ fn test_ipv6_to_int() {
+ let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
+ assert_eq!(u128::from(a), 0x112233445566778899aabbccddeeff11u128);
+ }
+
+ #[test]
+ fn test_int_to_ipv6() {
+ let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
+ assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a);
}
#[test]
fn next(&mut self) -> Option<SocketAddr> { self.0.next() }
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[unstable(feature = "lookup_host", reason = "unsure about the returned \
+ iterator and returning socket \
+ addresses",
+ issue = "27705")]
impl fmt::Debug for LookupHost {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("LookupHost { .. }")
self.0.write_timeout()
}
+ /// Receives data on the socket from the remote adress to which it is
+ /// connected, without removing that data from the queue. On success,
+ /// returns the number of bytes peeked.
+ ///
+ /// Successive calls return the same data. This is accomplished by passing
+ /// `MSG_PEEK` as a flag to the underlying `recv` system call.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// #![feature(peek)]
+ /// use std::net::TcpStream;
+ ///
+ /// let stream = TcpStream::connect("127.0.0.1:8000")
+ /// .expect("couldn't bind to address");
+ /// let mut buf = [0; 10];
+ /// let len = stream.peek(&mut buf).expect("peek failed");
+ /// ```
+ #[unstable(feature = "peek", issue = "38980")]
+ pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+ self.0.peek(buf)
+ }
+
/// Sets the value of the `TCP_NODELAY` option on this socket.
///
/// If set, this option disables the Nagle algorithm. This means that
Err(e) => panic!("unexpected error {}", e),
}
}
+
+ #[test]
+ fn peek() {
+ each_ip(&mut |addr| {
+ let (txdone, rxdone) = channel();
+
+ let srv = t!(TcpListener::bind(&addr));
+ let _t = thread::spawn(move|| {
+ let mut cl = t!(srv.accept()).0;
+ cl.write(&[1,3,3,7]).unwrap();
+ t!(rxdone.recv());
+ });
+
+ let mut c = t!(TcpStream::connect(&addr));
+ let mut b = [0; 10];
+ for _ in 1..3 {
+ let len = c.peek(&mut b).unwrap();
+ assert_eq!(len, 4);
+ }
+ let len = c.read(&mut b).unwrap();
+ assert_eq!(len, 4);
+
+ t!(c.set_nonblocking(true));
+ match c.peek(&mut b) {
+ Ok(_) => panic!("expected error"),
+ Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
+ Err(e) => panic!("unexpected error {}", e),
+ }
+ t!(txdone.send(()));
+ })
+ }
}
self.0.recv_from(buf)
}
+ /// Receives data from the socket, without removing it from the queue.
+ ///
+ /// Successive calls return the same data. This is accomplished by passing
+ /// `MSG_PEEK` as a flag to the underlying `recvfrom` system call.
+ ///
+ /// On success, returns the number of bytes peeked and the address from
+ /// whence the data came.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// #![feature(peek)]
+ /// use std::net::UdpSocket;
+ ///
+ /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
+ /// let mut buf = [0; 10];
+ /// let (number_of_bytes, src_addr) = socket.peek_from(&mut buf)
+ /// .expect("Didn't receive data");
+ /// ```
+ #[unstable(feature = "peek", issue = "38980")]
+ pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+ self.0.peek_from(buf)
+ }
+
/// Sends data on the socket to the given address. On success, returns the
/// number of bytes written.
///
self.0.recv(buf)
}
+ /// Receives data on the socket from the remote adress to which it is
+ /// connected, without removing that data from the queue. On success,
+ /// returns the number of bytes peeked.
+ ///
+ /// Successive calls return the same data. This is accomplished by passing
+ /// `MSG_PEEK` as a flag to the underlying `recv` system call.
+ ///
+ /// # Errors
+ ///
+ /// This method will fail if the socket is not connected. The `connect` method
+ /// will connect this socket to a remote address.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// #![feature(peek)]
+ /// use std::net::UdpSocket;
+ ///
+ /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
+ /// socket.connect("127.0.0.1:8080").expect("connect function failed");
+ /// let mut buf = [0; 10];
+ /// match socket.peek(&mut buf) {
+ /// Ok(received) => println!("received {} bytes", received),
+ /// Err(e) => println!("peek function failed: {:?}", e),
+ /// }
+ /// ```
+ #[unstable(feature = "peek", issue = "38980")]
+ pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+ self.0.peek(buf)
+ }
+
/// Moves this UDP socket into or out of nonblocking mode.
///
/// On Unix this corresponds to calling fcntl, and on Windows this
assert_eq!(b"hello world", &buf[..]);
}
+ #[test]
+ fn connect_send_peek_recv() {
+ each_ip(&mut |addr, _| {
+ let socket = t!(UdpSocket::bind(&addr));
+ t!(socket.connect(addr));
+
+ t!(socket.send(b"hello world"));
+
+ for _ in 1..3 {
+ let mut buf = [0; 11];
+ let size = t!(socket.peek(&mut buf));
+ assert_eq!(b"hello world", &buf[..]);
+ assert_eq!(size, 11);
+ }
+
+ let mut buf = [0; 11];
+ let size = t!(socket.recv(&mut buf));
+ assert_eq!(b"hello world", &buf[..]);
+ assert_eq!(size, 11);
+ })
+ }
+
+ #[test]
+ fn peek_from() {
+ each_ip(&mut |addr, _| {
+ let socket = t!(UdpSocket::bind(&addr));
+ t!(socket.send_to(b"hello world", &addr));
+
+ for _ in 1..3 {
+ let mut buf = [0; 11];
+ let (size, _) = t!(socket.peek_from(&mut buf));
+ assert_eq!(b"hello world", &buf[..]);
+ assert_eq!(size, 11);
+ }
+
+ let mut buf = [0; 11];
+ let (size, _) = t!(socket.recv_from(&mut buf));
+ assert_eq!(b"hello world", &buf[..]);
+ assert_eq!(size, 11);
+ })
+ }
+
#[test]
fn ttl() {
let ttl = 100;
#[doc(hidden)] __variant2,
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for c_void {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("c_void")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("AssertUnwindSafe")
}
}
+#[stable(feature = "default_for_pathbuf", since = "1.16.0")]
+impl Default for PathBuf {
+ fn default() -> Self {
+ PathBuf::new()
+ }
+}
+
#[stable(feature = "cow_from_path", since = "1.6.0")]
impl<'a> From<&'a Path> for Cow<'a, Path> {
#[inline]
fn into_inner(self) -> imp::Process { self.handle }
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Child {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Child")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for ChildStdin {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("ChildStdin { .. }")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for ChildStdout {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("ChildStdout { .. }")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for ChildStderr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("ChildStderr { .. }")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Stdio {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("Stdio { .. }")
///
/// # Examples
///
+/// Due to this function’s behavior regarding destructors, a conventional way
+/// to use the function is to extract the actual computation to another
+/// function and compute the exit code from its return value:
+///
/// ```
-/// use std::process;
+/// use std::io::{self, Write};
+///
+/// fn run_app() -> Result<(), ()> {
+/// // Application logic here
+/// Ok(())
+/// }
///
-/// process::exit(0);
+/// fn main() {
+/// ::std::process::exit(match run_app() {
+/// Ok(_) => 0,
+/// Err(err) => {
+/// writeln!(io::stderr(), "error: {:?}", err).unwrap();
+/// 1
+/// }
+/// });
+/// }
/// ```
///
/// Due to [platform-specific behavior], the exit code for this example will be
#[stable(feature = "rust1", since = "1.0.0")]
pub struct BarrierWaitResult(bool);
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Barrier {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("Barrier { .. }")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for BarrierWaitResult {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("BarrierWaitResult")
/// consumes no CPU time while waiting for an event to occur. Condition
/// variables are typically associated with a boolean predicate (a condition)
/// and a mutex. The predicate is always verified inside of the mutex before
-/// determining that thread must block.
+/// determining that a thread must block.
///
/// Functions in this module will block the current **thread** of execution and
/// are bindings to system-provided condition variables where possible. Note
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Condvar {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("Condvar { .. }")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("MutexGuard")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Once {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("Once { .. }")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, T: fmt::Debug> fmt::Debug for RwLockReadGuard<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("RwLockReadGuard")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("RwLockWriteGuard")
// casts and rely on manual lowering to `stat` if the raw type is desired.
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
+ #[stable(feature = "metadata_ext", since = "1.1.0")]
+ fn dev(&self) -> u64;
+ #[stable(feature = "metadata_ext", since = "1.1.0")]
+ fn ino(&self) -> u64;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn mode(&self) -> u32;
#[stable(feature = "metadata_ext", since = "1.1.0")]
#[stable(feature = "metadata_ext", since = "1.1.0")]
impl MetadataExt for fs::Metadata {
+ fn dev(&self) -> u64 {
+ self.as_inner().as_inner().st_dev as u64
+ }
+ fn ino(&self) -> u64 {
+ self.as_inner().as_inner().st_ino as u64
+ }
fn mode(&self) -> u32 {
self.as_inner().as_inner().st_mode as u32
}
/// an error indicating why the exec (or another part of the setup of the
/// `Command`) failed.
///
+ /// `exec` not returning has the same implications as calling
+ /// [`process::exit`] – no destructors on the current stack or any other
+ /// thread’s stack will be run. Therefore, it is recommended to only call
+ /// `exec` at a point where it is fine to not run any destructors. Note,
+ /// that the `execvp` syscall independently guarantees that all memory is
+ /// freed and all file descriptors with the `CLOEXEC` option (set by default
+ /// on all file descriptors opened by the standard library) are closed.
+ ///
/// This function, unlike `spawn`, will **not** `fork` the process to create
/// a new child. Like spawn, however, the default behavior for the stdio
/// descriptors will be to inherited from the current process.
///
+ /// [`process::exit`]: ../../../process/fn.exit.html
+ ///
/// # Notes
///
/// The process may be in a "broken state" if this function returns in
pub fn set_cloexec(&self) -> io::Result<()> {
unsafe {
let previous = cvt(libc::fcntl(self.fd, libc::F_GETFD))?;
- cvt(libc::fcntl(self.fd, libc::F_SETFD, previous | libc::FD_CLOEXEC))?;
+ let new = previous | libc::FD_CLOEXEC;
+ if new != previous {
+ cvt(libc::fcntl(self.fd, libc::F_SETFD, new))?;
+ }
+ Ok(())
+ }
+ }
+
+ #[cfg(target_os = "linux")]
+ pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+ unsafe {
+ let v = nonblocking as c_int;
+ cvt(libc::ioctl(self.fd, libc::FIONBIO, &v))?;
Ok(())
}
}
+ #[cfg(not(target_os = "linux"))]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
unsafe {
let previous = cvt(libc::fcntl(self.fd, libc::F_GETFL))?;
} else {
previous & !libc::O_NONBLOCK
};
- cvt(libc::fcntl(self.fd, libc::F_SETFL, new))?;
+ if new != previous {
+ cvt(libc::fcntl(self.fd, libc::F_SETFL, new))?;
+ }
Ok(())
}
}
use ffi::CStr;
use io;
-use libc::{self, c_int, size_t, sockaddr, socklen_t, EAI_SYSTEM};
+use libc::{self, c_int, c_void, size_t, sockaddr, socklen_t, EAI_SYSTEM, MSG_PEEK};
+use mem;
use net::{SocketAddr, Shutdown};
use str;
use sys::fd::FileDesc;
use sys_common::{AsInner, FromInner, IntoInner};
-use sys_common::net::{getsockopt, setsockopt};
+use sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr};
use time::Duration;
pub use sys::{cvt, cvt_r};
self.0.duplicate().map(Socket)
}
+ fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> {
+ let ret = cvt(unsafe {
+ libc::recv(self.0.raw(),
+ buf.as_mut_ptr() as *mut c_void,
+ buf.len(),
+ flags)
+ })?;
+ Ok(ret as usize)
+ }
+
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
- self.0.read(buf)
+ self.recv_with_flags(buf, 0)
+ }
+
+ pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+ self.recv_with_flags(buf, MSG_PEEK)
+ }
+
+ fn recv_from_with_flags(&self, buf: &mut [u8], flags: c_int)
+ -> io::Result<(usize, SocketAddr)> {
+ let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
+ let mut addrlen = mem::size_of_val(&storage) as libc::socklen_t;
+
+ let n = cvt(unsafe {
+ libc::recvfrom(self.0.raw(),
+ buf.as_mut_ptr() as *mut c_void,
+ buf.len(),
+ flags,
+ &mut storage as *mut _ as *mut _,
+ &mut addrlen)
+ })?;
+ Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?))
+ }
+
+ pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+ self.recv_from_with_flags(buf, 0)
+ }
+
+ pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+ self.recv_from_with_flags(buf, MSG_PEEK)
}
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
use libc::{self, c_int};
use mem;
use ptr;
-use sys::cvt_r;
+use sys::{cvt, cvt_r};
use sys::fd::FileDesc;
////////////////////////////////////////////////////////////////////////////////
// CLOEXEC flag is to use the `pipe2` syscall on Linux. This was added in
// 2.6.27, however, and because we support 2.6.18 we must detect this
// support dynamically.
- if cfg!(target_os = "linux") {
+ if cfg!(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_os = "openbsd"))
+ {
weak! { fn pipe2(*mut c_int, c_int) -> c_int }
if let Some(pipe) = pipe2.get() {
- match cvt_r(|| unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
- Ok(_) => {
- return Ok((AnonPipe(FileDesc::new(fds[0])),
- AnonPipe(FileDesc::new(fds[1]))))
- }
- Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {}
- Err(e) => return Err(e),
- }
+ cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) })?;
+ return Ok((AnonPipe(FileDesc::new(fds[0])),
+ AnonPipe(FileDesc::new(fds[1]))));
}
}
- if unsafe { libc::pipe(fds.as_mut_ptr()) == 0 } {
- let fd0 = FileDesc::new(fds[0]);
- let fd1 = FileDesc::new(fds[1]);
- Ok((AnonPipe::from_fd(fd0)?, AnonPipe::from_fd(fd1)?))
- } else {
- Err(io::Error::last_os_error())
- }
+ cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;
+
+ let fd0 = FileDesc::new(fds[0]);
+ let fd1 = FileDesc::new(fds[1]);
+ fd0.set_cloexec()?;
+ fd1.set_cloexec()?;
+ Ok((AnonPipe(fd0), AnonPipe(fd1)))
}
impl AnonPipe {
- pub fn from_fd(fd: FileDesc) -> io::Result<AnonPipe> {
- fd.set_cloexec()?;
- Ok(AnonPipe(fd))
- }
-
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
}
#[test]
#[cfg_attr(target_os = "macos", ignore)]
#[cfg_attr(target_os = "nacl", ignore)] // no signals on NaCl.
+ // When run under our current QEMU emulation test suite this test fails,
+ // although the reason isn't very clear as to why. For now this test is
+ // ignored there.
+ #[cfg_attr(target_arch = "arm", ignore)]
fn test_process_mask() {
unsafe {
// Test to make sure that a signal mask does not get inherited.
// Either EOF or failure (EPIPE) is okay.
let mut buf = [0; 5];
if let Ok(ret) = stdout_read.read(&mut buf) {
- assert!(ret == 0);
+ assert_eq!(ret, 0);
}
t!(cat.wait());
pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4;
pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1;
+pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2;
// Note that these are not actually HANDLEs, just values to pass to GetStdHandle
pub const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD;
pub const IP_DROP_MEMBERSHIP: c_int = 13;
pub const IPV6_ADD_MEMBERSHIP: c_int = 12;
pub const IPV6_DROP_MEMBERSHIP: c_int = 13;
+pub const MSG_PEEK: c_int = 0x2;
#[repr(C)]
pub struct ip_mreq {
let src = to_u16s(src)?;
let dst = to_u16s(dst)?;
let flags = if dir { c::SYMBOLIC_LINK_FLAG_DIRECTORY } else { 0 };
- cvt(unsafe {
- c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as c::BOOL
- })?;
+ // Formerly, symlink creation required the SeCreateSymbolicLink privilege. For the Windows 10
+ // Creators Update, Microsoft loosened this to allow unprivileged symlink creation if the
+ // computer is in Developer Mode, but SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE must be
+ // added to dwFlags to opt into this behaviour.
+ let result = cvt(unsafe {
+ c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(),
+ flags | c::SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) as c::BOOL
+ });
+ if let Err(err) = result {
+ if err.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as i32) {
+ // Older Windows objects to SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE,
+ // so if we encounter ERROR_INVALID_PARAMETER, retry without that flag.
+ cvt(unsafe {
+ c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as c::BOOL
+ })?;
+ } else {
+ return Err(err);
+ }
+ }
Ok(())
}
Ok(socket)
}
- pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+ fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> {
// On unix when a socket is shut down all further reads return 0, so we
// do the same on windows to map a shut down socket to returning EOF.
let len = cmp::min(buf.len(), i32::max_value() as usize) as i32;
unsafe {
- match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, 0) {
+ match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, flags) {
-1 if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0),
-1 => Err(last_error()),
n => Ok(n as usize)
}
}
+ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+ self.recv_with_flags(buf, 0)
+ }
+
+ pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+ self.recv_with_flags(buf, c::MSG_PEEK)
+ }
+
+ fn recv_from_with_flags(&self, buf: &mut [u8], flags: c_int)
+ -> io::Result<(usize, SocketAddr)> {
+ let mut storage: c::SOCKADDR_STORAGE_LH = unsafe { mem::zeroed() };
+ let mut addrlen = mem::size_of_val(&storage) as c::socklen_t;
+ let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
+
+ // On unix when a socket is shut down all further reads return 0, so we
+ // do the same on windows to map a shut down socket to returning EOF.
+ unsafe {
+ match c::recvfrom(self.0,
+ buf.as_mut_ptr() as *mut c_void,
+ len,
+ flags,
+ &mut storage as *mut _ as *mut _,
+ &mut addrlen) {
+ -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => {
+ Ok((0, net::sockaddr_to_addr(&storage, addrlen as usize)?))
+ },
+ -1 => Err(last_error()),
+ n => Ok((n as usize, net::sockaddr_to_addr(&storage, addrlen as usize)?)),
+ }
+ }
+ }
+
+ pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+ self.recv_from_with_flags(buf, 0)
+ }
+
+ pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+ self.recv_from_with_flags(buf, c::MSG_PEEK)
+ }
+
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
let mut me = self;
(&mut me).read_to_end(buf)
}
}
-fn sockaddr_to_addr(storage: &c::sockaddr_storage,
+pub fn sockaddr_to_addr(storage: &c::sockaddr_storage,
len: usize) -> io::Result<SocketAddr> {
match storage.ss_family as c_int {
c::AF_INET => {
self.inner.timeout(c::SO_SNDTIMEO)
}
+ pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+ self.inner.peek(buf)
+ }
+
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf)
}
}
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
- let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() };
- let mut addrlen = mem::size_of_val(&storage) as c::socklen_t;
- let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
+ self.inner.recv_from(buf)
+ }
- let n = cvt(unsafe {
- c::recvfrom(*self.inner.as_inner(),
- buf.as_mut_ptr() as *mut c_void,
- len, 0,
- &mut storage as *mut _ as *mut _, &mut addrlen)
- })?;
- Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?))
+ pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+ self.inner.peek_from(buf)
}
pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
self.inner.read(buf)
}
+ pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+ self.inner.peek(buf)
+ }
+
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
let ret = cvt(unsafe {
init: fn() -> T,
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<T: 'static> fmt::Debug for LocalKey<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("LocalKey { .. }")
marker: marker::PhantomData<Cell<T>>,
}
- #[stable(feature = "std_debug", since = "1.15.0")]
impl<T> fmt::Debug for Key<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("Key { .. }")
}
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[unstable(feature = "thread_id", issue = "21507")]
impl fmt::Debug for ThreadId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("ThreadId { .. }")
fn into_inner(self) -> imp::Thread { self.0.native.unwrap() }
}
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
impl<T> fmt::Debug for JoinHandle<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("JoinHandle { .. }")
}
}
-#[stable(feature = "char_struct_display", since = "1.17.0")]
impl fmt::Display for CaseMappingIter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
}
}
-#[stable(feature = "char_struct_display", since = "1.17.0")]
+#[stable(feature = "char_struct_display", since = "1.16.0")]
impl fmt::Display for ToLowercase {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
-#[stable(feature = "char_struct_display", since = "1.17.0")]
+#[stable(feature = "char_struct_display", since = "1.16.0")]
impl fmt::Display for ToUppercase {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
syntax_pos = { path = "../libsyntax_pos" }
rustc_errors = { path = "../librustc_errors" }
rustc_data_structures = { path = "../librustc_data_structures" }
-rustc_i128 = { path = "../librustc_i128" }
use serialize::{self, Encodable, Decodable, Encoder, Decoder};
-use rustc_i128::{u128, i128};
-
/// An identifier contains a Name (index into the interner
/// table) and a SyntaxContext to track renaming and
/// macro expansion per Flatt et al., "Macros That Work Together"
Symbol::intern("doc"),
Symbol::intern(&strip_doc_comment_decoration(&comment.as_str())));
if self.style == ast::AttrStyle::Outer {
- f(&mk_attr_outer(self.id, meta))
+ f(&mk_attr_outer(self.span, self.id, meta))
} else {
- f(&mk_attr_inner(self.id, meta))
+ f(&mk_attr_inner(self.span, self.id, meta))
}
} else {
f(self)
}
/// Returns an inner attribute with the given value.
-pub fn mk_attr_inner(id: AttrId, item: MetaItem) -> Attribute {
- mk_spanned_attr_inner(DUMMY_SP, id, item)
+pub fn mk_attr_inner(span: Span, id: AttrId, item: MetaItem) -> Attribute {
+ mk_spanned_attr_inner(span, id, item)
}
/// Returns an innter attribute with the given value and span.
/// Returns an outer attribute with the given value.
-pub fn mk_attr_outer(id: AttrId, item: MetaItem) -> Attribute {
- mk_spanned_attr_outer(DUMMY_SP, id, item)
+pub fn mk_attr_outer(span: Span, id: AttrId, item: MetaItem) -> Attribute {
+ mk_spanned_attr_outer(span, id, item)
}
/// Returns an outer attribute with the given value and span.
pub use self::SyntaxExtension::{MultiDecorator, MultiModifier, NormalTT, IdentTT};
-use ast::{self, Attribute, Name, PatKind};
+use ast::{self, Attribute, Name, PatKind, MetaItem};
use attr::HasAttrs;
use codemap::{self, CodeMap, ExpnInfo, Spanned, respan};
use syntax_pos::{Span, ExpnId, NO_EXPANSION};
}
}
+pub type BuiltinDeriveFn =
+ for<'cx> fn(&'cx mut ExtCtxt, Span, &MetaItem, &Annotatable, &mut FnMut(Annotatable));
+
/// An enum representing the different kinds of syntax extensions.
pub enum SyntaxExtension {
/// A syntax extension that is attached to an item and creates new items
///
IdentTT(Box<IdentMacroExpander>, Option<Span>, bool),
- CustomDerive(Box<MultiItemModifier>),
+ /// An attribute-like procedural macro. TokenStream -> TokenStream.
+ /// The input is the annotated item.
+ /// Allows generating code to implement a Trait for a given struct
+ /// or enum item.
+ ProcMacroDerive(Box<MultiItemModifier>),
+
+ /// An attribute-like procedural macro that derives a builtin trait.
+ BuiltinDerive(BuiltinDeriveFn),
}
pub type NamedSyntaxExtension = (Name, SyntaxExtension);
fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute>;
fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
-> Result<Rc<SyntaxExtension>, Determinacy>;
+ fn resolve_builtin_macro(&mut self, tname: Name) -> Result<Rc<SyntaxExtension>, Determinacy>;
+ fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
+ -> Result<Rc<SyntaxExtension>, Determinacy>;
}
#[derive(Copy, Clone, Debug)]
-> Result<Rc<SyntaxExtension>, Determinacy> {
Err(Determinacy::Determined)
}
+ fn resolve_builtin_macro(&mut self, _tname: Name) -> Result<Rc<SyntaxExtension>, Determinacy> {
+ Err(Determinacy::Determined)
+ }
+ fn resolve_derive_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool)
+ -> Result<Rc<SyntaxExtension>, Determinacy> {
+ Err(Determinacy::Determined)
+ }
}
#[derive(Clone)]
use ext::base::ExtCtxt;
use ptr::P;
use symbol::{Symbol, keywords};
-use rustc_i128::u128;
// Transitional reexports so qquote can find the paths it is looking for
mod syntax {
--- /dev/null
+// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ast::Name;
+use attr;
+use ast::{self, NestedMetaItem}; use ext::base::{ExtCtxt, SyntaxExtension};
+use codemap;
+use ext::build::AstBuilder;
+use feature_gate;
+use symbol::Symbol;
+use syntax_pos::Span;
+
+pub fn derive_attr_trait<'a>(cx: &mut ExtCtxt, attr: &'a ast::Attribute)
+ -> Option<&'a NestedMetaItem> {
+ if attr.name() != "derive" {
+ return None;
+ }
+ if attr.value_str().is_some() {
+ cx.span_err(attr.span, "unexpected value in `derive`");
+ return None;
+ }
+
+ let traits = attr.meta_item_list().unwrap_or(&[]);
+
+ if traits.is_empty() {
+ cx.span_warn(attr.span, "empty trait list in `derive`");
+ return None;
+ }
+
+ return traits.get(0);
+}
+
+pub fn verify_derive_attrs(cx: &mut ExtCtxt, attrs: &[ast::Attribute]) {
+ for attr in attrs {
+ if attr.name() != "derive" {
+ continue;
+ }
+
+ if attr.value_str().is_some() {
+ cx.span_err(attr.span, "unexpected value in `derive`");
+ }
+
+ let traits = attr.meta_item_list().unwrap_or(&[]).to_owned();
+
+ if traits.is_empty() {
+ cx.span_warn(attr.span, "empty trait list in `derive`");
+ attr::mark_used(&attr);
+ continue;
+ }
+ for titem in traits {
+ if titem.word().is_none() {
+ cx.span_err(titem.span, "malformed `derive` entry");
+ }
+ }
+ }
+}
+
+#[derive(PartialEq, Debug, Clone, Copy)]
+pub enum DeriveType {
+ Legacy,
+ ProcMacro,
+ Builtin
+}
+
+impl DeriveType {
+ // Classify a derive trait name by resolving the macro.
+ pub fn classify(cx: &mut ExtCtxt, tname: Name) -> DeriveType {
+ let legacy_derive_name = Symbol::intern(&format!("derive_{}", tname));
+
+ if let Ok(_) = cx.resolver.resolve_builtin_macro(legacy_derive_name) {
+ return DeriveType::Legacy;
+ }
+
+ match cx.resolver.resolve_builtin_macro(tname) {
+ Ok(ext) => match *ext {
+ SyntaxExtension::BuiltinDerive(..) => DeriveType::Builtin,
+ _ => DeriveType::ProcMacro,
+ },
+ Err(_) => DeriveType::ProcMacro,
+ }
+ }
+}
+
+pub fn get_derive_attr(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>,
+ derive_type: DeriveType) -> Option<ast::Attribute> {
+ for i in 0..attrs.len() {
+ if attrs[i].name() != "derive" {
+ continue;
+ }
+
+ if attrs[i].value_str().is_some() {
+ continue;
+ }
+
+ let mut traits = attrs[i].meta_item_list().unwrap_or(&[]).to_owned();
+
+ // First, weed out malformed #[derive]
+ traits.retain(|titem| titem.word().is_some());
+
+ let mut titem = None;
+
+ // See if we can find a matching trait.
+ for j in 0..traits.len() {
+ let tname = match traits[j].name() {
+ Some(tname) => tname,
+ _ => continue,
+ };
+
+ if DeriveType::classify(cx, tname) == derive_type {
+ titem = Some(traits.remove(j));
+ break;
+ }
+ }
+
+ // If we find a trait, remove the trait from the attribute.
+ if let Some(titem) = titem {
+ if traits.len() == 0 {
+ attrs.remove(i);
+ } else {
+ let derive = Symbol::intern("derive");
+ let mitem = cx.meta_list(titem.span, derive, traits);
+ attrs[i] = cx.attribute(titem.span, mitem);
+ }
+ let derive = Symbol::intern("derive");
+ let mitem = cx.meta_list(titem.span, derive, vec![titem]);
+ return Some(cx.attribute(mitem.span, mitem));
+ }
+ }
+ return None;
+}
+
+fn allow_unstable(cx: &mut ExtCtxt, span: Span, attr_name: &str) -> Span {
+ Span {
+ expn_id: cx.codemap().record_expansion(codemap::ExpnInfo {
+ call_site: span,
+ callee: codemap::NameAndSpan {
+ format: codemap::MacroAttribute(Symbol::intern(attr_name)),
+ span: Some(span),
+ allow_internal_unstable: true,
+ },
+ }),
+ ..span
+ }
+}
+
+pub fn add_derived_markers(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>) {
+ if attrs.is_empty() {
+ return;
+ }
+
+ let titems = attrs.iter().filter(|a| {
+ a.name() == "derive"
+ }).flat_map(|a| {
+ a.meta_item_list().unwrap_or(&[]).iter()
+ }).filter_map(|titem| {
+ titem.name()
+ }).collect::<Vec<_>>();
+
+ let span = attrs[0].span;
+
+ if !attrs.iter().any(|a| a.name() == "structural_match") &&
+ titems.iter().any(|t| *t == "PartialEq") && titems.iter().any(|t| *t == "Eq") {
+ let structural_match = Symbol::intern("structural_match");
+ let span = allow_unstable(cx, span, "derive(PartialEq, Eq)");
+ let meta = cx.meta_word(span, structural_match);
+ attrs.push(cx.attribute(span, meta));
+ }
+
+ if !attrs.iter().any(|a| a.name() == "rustc_copy_clone_marker") &&
+ titems.iter().any(|t| *t == "Copy") && titems.iter().any(|t| *t == "Clone") {
+ let structural_match = Symbol::intern("rustc_copy_clone_marker");
+ let span = allow_unstable(cx, span, "derive(Copy, Clone)");
+ let meta = cx.meta_word(span, structural_match);
+ attrs.push(cx.attribute(span, meta));
+ }
+}
+
+pub fn find_derive_attr(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>)
+ -> Option<ast::Attribute> {
+ verify_derive_attrs(cx, attrs);
+ get_derive_attr(cx, attrs, DeriveType::Legacy).and_then(|a| {
+ let titem = derive_attr_trait(cx, &a);
+ titem.and_then(|titem| {
+ let tword = titem.word().unwrap();
+ let tname = tword.name();
+ if !cx.ecfg.enable_custom_derive() {
+ feature_gate::emit_feature_err(
+ &cx.parse_sess,
+ "custom_derive",
+ titem.span,
+ feature_gate::GateIssue::Language,
+ feature_gate::EXPLAIN_CUSTOM_DERIVE
+ );
+ None
+ } else {
+ let name = Symbol::intern(&format!("derive_{}", tname));
+ if !cx.resolver.is_whitelisted_legacy_custom_derive(name) {
+ cx.span_warn(titem.span,
+ feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE);
+ }
+ let mitem = cx.meta_word(titem.span, name);
+ Some(cx.attribute(mitem.span, mitem))
+ }
+ })
+ }).or_else(|| {
+ get_derive_attr(cx, attrs, DeriveType::ProcMacro)
+ }).or_else(|| {
+ add_derived_markers(cx, attrs);
+ get_derive_attr(cx, attrs, DeriveType::Builtin)
+ })
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use ast::{Block, Ident, Mac_, PatKind};
+use ast::{self, Block, Ident, Mac_, PatKind};
use ast::{Name, MacStmtStyle, StmtKind, ItemKind};
-use ast;
-use ext::hygiene::Mark;
-use ext::placeholders::{placeholder, PlaceholderExpander};
use attr::{self, HasAttrs};
use codemap::{ExpnInfo, NameAndSpan, MacroBang, MacroAttribute};
-use syntax_pos::{self, Span, ExpnId};
use config::{is_test_or_bench, StripUnconfigured};
use ext::base::*;
+use ext::derive::{find_derive_attr, derive_attr_trait};
+use ext::hygiene::Mark;
+use ext::placeholders::{placeholder, PlaceholderExpander};
use feature_gate::{self, Features};
use fold;
use fold::*;
-use parse::{ParseSess, DirectoryOwnership, PResult, filemap_to_tts};
use parse::parser::Parser;
use parse::token;
+use parse::{ParseSess, DirectoryOwnership, PResult, filemap_to_tts};
use print::pprust;
use ptr::P;
use std_inject;
+use symbol::Symbol;
use symbol::keywords;
+use syntax_pos::{self, Span, ExpnId};
use tokenstream::{TokenTree, TokenStream};
use util::small_vector::SmallVector;
use visit::Visitor;
attr: ast::Attribute,
item: Annotatable,
},
+ Derive {
+ attr: ast::Attribute,
+ item: Annotatable,
+ },
}
impl Invocation {
match self.kind {
InvocationKind::Bang { span, .. } => span,
InvocationKind::Attr { ref attr, .. } => attr.span,
+ InvocationKind::Derive { ref attr, .. } => attr.span,
}
}
}
let path = ast::Path::from_ident(attr.span, ident);
self.cx.resolver.resolve_macro(scope, &path, force)
}
+ InvocationKind::Derive { ref attr, .. } => {
+ let titem = derive_attr_trait(self.cx, &attr).unwrap();
+ let tname = titem.name().expect("Expected derive macro name");
+ let ident = Ident::with_empty_ctxt(tname);
+ let path = ast::Path::from_ident(attr.span, ident);
+ self.cx.resolver.resolve_derive_macro(scope, &path, force)
+ }
};
let ext = match resolution {
Ok(ext) => Some(ext),
match invoc.kind {
InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext),
InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext),
+ InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext),
}
}
let tok_result = mac.expand(self.cx, attr.span, attr_toks, item_toks);
self.parse_expansion(tok_result, kind, name, attr.span)
}
- SyntaxExtension::CustomDerive(_) => {
+ SyntaxExtension::ProcMacroDerive(..) | SyntaxExtension::BuiltinDerive(..) => {
self.cx.span_err(attr.span, &format!("`{}` is a derive mode", name));
kind.dummy(attr.span)
}
return kind.dummy(span);
}
- SyntaxExtension::CustomDerive(..) => {
+ SyntaxExtension::ProcMacroDerive(..) | SyntaxExtension::BuiltinDerive(..) => {
self.cx.span_err(path.span, &format!("`{}` is a derive mode", extname));
return kind.dummy(span);
}
})
}
+ /// Expand a derive invocation. Returns the result of expansion.
+ fn expand_derive_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
+ let Invocation { expansion_kind: kind, .. } = invoc;
+ let (attr, item) = match invoc.kind {
+ InvocationKind::Derive { attr, item } => (attr, item),
+ _ => unreachable!(),
+ };
+
+ attr::mark_used(&attr);
+ let titem = derive_attr_trait(self.cx, &attr).unwrap();
+ let tname = ast::Ident::with_empty_ctxt(titem.name().unwrap());
+ let name = Symbol::intern(&format!("derive({})", tname));
+ let mitem = &attr.value;
+
+ self.cx.bt_push(ExpnInfo {
+ call_site: attr.span,
+ callee: NameAndSpan {
+ format: MacroAttribute(attr.name()),
+ span: Some(attr.span),
+ allow_internal_unstable: false,
+ }
+ });
+
+ match *ext {
+ SyntaxExtension::ProcMacroDerive(ref ext) => {
+ let span = Span {
+ expn_id: self.cx.codemap().record_expansion(ExpnInfo {
+ call_site: mitem.span,
+ callee: NameAndSpan {
+ format: MacroAttribute(Symbol::intern(&format!("derive({})", tname))),
+ span: None,
+ allow_internal_unstable: false,
+ },
+ }),
+ ..mitem.span
+ };
+ return kind.expect_from_annotatables(ext.expand(self.cx, span, &mitem, item));
+ }
+ SyntaxExtension::BuiltinDerive(func) => {
+ let span = Span {
+ expn_id: self.cx.codemap().record_expansion(ExpnInfo {
+ call_site: titem.span,
+ callee: NameAndSpan {
+ format: MacroAttribute(name),
+ span: None,
+ allow_internal_unstable: true,
+ },
+ }),
+ ..titem.span
+ };
+ let mut items = Vec::new();
+ func(self.cx, span, &mitem, &item, &mut |a| {
+ items.push(a)
+ });
+ items.insert(0, item);
+ return kind.expect_from_annotatables(items);
+ }
+ _ => {
+ let msg = &format!("macro `{}` may not be used for derive attributes", name);
+ self.cx.span_err(attr.span, &msg);
+ kind.dummy(attr.span)
+ }
+ }
+ }
+
fn parse_expansion(&mut self, toks: TokenStream, kind: ExpansionKind, name: Name, span: Span)
-> Expansion {
let mut parser = self.cx.new_parser_from_tts(&toks.trees().cloned().collect::<Vec<_>>());
fn collect_attr(&mut self, attr: ast::Attribute, item: Annotatable, kind: ExpansionKind)
-> Expansion {
- self.collect(kind, InvocationKind::Attr { attr: attr, item: item })
+ let invoc_kind = if attr.name() == "derive" {
+ if kind == ExpansionKind::TraitItems || kind == ExpansionKind::ImplItems {
+ self.cx.span_err(attr.span, "`derive` can be only be applied to items");
+ return kind.expect_from_annotatables(::std::iter::once(item));
+ }
+ InvocationKind::Derive { attr: attr, item: item }
+ } else {
+ InvocationKind::Attr { attr: attr, item: item }
+ };
+
+ self.collect(kind, invoc_kind)
}
// If `item` is an attr invocation, remove and return the macro attribute.
fn classify_item<T: HasAttrs>(&mut self, mut item: T) -> (T, Option<ast::Attribute>) {
let mut attr = None;
+
item = item.map_attrs(|mut attrs| {
- attr = self.cx.resolver.find_attr_invoc(&mut attrs);
+ attr = self.cx.resolver.find_attr_invoc(&mut attrs).or_else(|| {
+ find_derive_attr(self.cx, &mut attrs)
+ });
+
attrs
});
+
(item, attr)
}
pub use parse::new_parser_from_tts;
pub use syntax_pos::{BytePos, Span, DUMMY_SP};
pub use codemap::{dummy_spanned};
- use rustc_i128::{u128};
pub trait ToTokens {
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree>;
(active, abi_unadjusted, "1.16.0", None),
// Macros 1.1
- (active, proc_macro, "1.16.0", Some(35900)),
+ (active, proc_macro, "1.16.0", Some(38356)),
// Allows attributes on struct literal fields.
(active, struct_field_attributes, "1.16.0", Some(38814)),
+ // Allows #[link(kind="static-nobundle"...]
+ (active, static_nobundle, "1.16.0", Some(37403)),
+
// `extern "msp430-interrupt" fn()`
(active, abi_msp430_interrupt, "1.16.0", Some(38487)),
);
(accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
(accepted, item_like_imports, "1.14.0", Some(35120)),
// Allows using `Self` and associated types in struct expressions and patterns.
- (accepted, more_struct_aliases, "1.14.0", Some(37544)),
+ (accepted, more_struct_aliases, "1.16.0", Some(37544)),
);
// (changing above list without updating src/doc/reference.md makes @cmr sad)
#![feature(unicode)]
#![feature(rustc_diagnostic_macros)]
#![feature(specialization)]
+#![feature(i128_type)]
extern crate serialize;
#[macro_use] extern crate log;
extern crate syntax_pos;
extern crate rustc_data_structures;
-extern crate rustc_i128;
-
extern crate serialize as rustc_serialize; // used by deriving
// A variant of 'try!' that panics on an Err. This is used as a crutch on the
pub mod ext {
pub mod base;
pub mod build;
+ pub mod derive;
pub mod expand;
pub mod placeholders;
pub mod hygiene;
use std::rc::Rc;
use std::str;
-use rustc_i128::u128;
-
pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a>>;
#[macro_use]
use std::rc::Rc;
use std::slice;
-use rustc_i128::u128;
-
bitflags! {
flags Restrictions: u8 {
const RESTRICTION_STMT_EXPR = 1 << 0,
}
// Assemble the span.
+ // FIXME(#39450) This is bogus if part of the path is macro generated.
let span = mk_sp(lo, self.prev_span.hi);
// Assemble the result.
Some(f) => f,
None => continue,
};
- err.help(&format!("try parenthesizing the first index; e.g., `(foo.{}){}`",
- float.trunc() as usize,
- format!(".{}", fstr.splitn(2, ".").last().unwrap())));
+ let sugg = pprust::to_string(|s| {
+ use print::pprust::PrintState;
+ use print::pp::word;
+ s.popen()?;
+ s.print_expr(&e)?;
+ word(&mut s.s, ".")?;
+ s.print_usize(float.trunc() as usize)?;
+ s.pclose()?;
+ word(&mut s.s, ".")?;
+ word(&mut s.s, fstr.splitn(2, ".").last().unwrap())
+ });
+ err.span_suggestion(
+ prev_span,
+ "try parenthesizing the first index",
+ sugg);
}
return Err(err);
if self.eat(&token::Semi) {
stmt_span.hi = self.prev_span.hi;
}
- e.span_help(stmt_span, "try placing this code inside a block");
+ let sugg = pprust::to_string(|s| {
+ use print::pprust::{PrintState, INDENT_UNIT};
+ s.ibox(INDENT_UNIT)?;
+ s.bopen()?;
+ s.print_stmt(&stmt)?;
+ s.bclose_maybe_open(stmt.span, INDENT_UNIT, false)
+ });
+ e.span_suggestion(stmt_span, "try placing this code inside a block", sugg);
}
Err(mut e) => {
self.recover_stmt_(SemiColonMode::Break);
use ptr::P;
use std_inject;
use symbol::{Symbol, keywords};
+use syntax_pos::DUMMY_SP;
use tokenstream::{self, TokenTree};
-use rustc_i128::i128;
-
use std::ascii;
use std::io::{self, Write, Read};
use std::iter;
// #![feature(prelude_import)]
let prelude_import_meta = attr::mk_list_word_item(Symbol::intern("prelude_import"));
let list = attr::mk_list_item(Symbol::intern("feature"), vec![prelude_import_meta]);
- let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), list);
+ let fake_attr = attr::mk_attr_inner(DUMMY_SP, attr::mk_attr_id(), list);
s.print_attribute(&fake_attr)?;
// #![no_std]
let no_std_meta = attr::mk_word_item(Symbol::intern("no_std"));
- let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), no_std_meta);
+ let fake_attr = attr::mk_attr_inner(DUMMY_SP, attr::mk_attr_id(), no_std_meta);
s.print_attribute(&fake_attr)?;
}
let crate_name = Symbol::intern(&alt_std_name.unwrap_or(name.to_string()));
krate.module.items.insert(0, P(ast::Item {
- attrs: vec![attr::mk_attr_outer(attr::mk_attr_id(),
+ attrs: vec![attr::mk_attr_outer(DUMMY_SP,
+ attr::mk_attr_id(),
attr::mk_word_item(Symbol::intern("macro_use")))],
vis: ast::Visibility::Inherited,
node: ast::ItemKind::ExternCrate(Some(crate_name)),
$(
#[allow(non_upper_case_globals)]
pub const $konst: Keyword = Keyword {
- ident: ast::Ident::with_empty_ctxt(ast::Name($index))
+ ident: ast::Ident::with_empty_ctxt(super::Symbol($index))
};
)*
}
#[cfg(test)]
mod tests {
use super::*;
- use ast::Name;
#[test]
fn interner_tests() {
let mut i: Interner = Interner::new();
// first one is zero:
- assert_eq!(i.intern("dog"), Name(0));
+ assert_eq!(i.intern("dog"), Symbol(0));
// re-use gets the same entry:
- assert_eq!(i.intern ("dog"), Name(0));
+ assert_eq!(i.intern ("dog"), Symbol(0));
// different string gets a different #:
- assert_eq!(i.intern("cat"), Name(1));
- assert_eq!(i.intern("cat"), Name(1));
+ assert_eq!(i.intern("cat"), Symbol(1));
+ assert_eq!(i.intern("cat"), Symbol(1));
// dog is still at zero
- assert_eq!(i.intern("dog"), Name(0));
+ assert_eq!(i.intern("dog"), Symbol(0));
// gensym gets 3
- assert_eq!(i.gensym("zebra"), Name(2));
+ assert_eq!(i.gensym("zebra"), Symbol(2));
// gensym of same string gets new number :
- assert_eq!(i.gensym("zebra"), Name(3));
+ assert_eq!(i.gensym("zebra"), Symbol(3));
// gensym of *existing* string gets new number:
- assert_eq!(i.gensym("dog"), Name(4));
+ assert_eq!(i.gensym("dog"), Symbol(4));
}
}
let dead_code_str = Symbol::intern("dead_code");
let word_vec = vec![attr::mk_list_word_item(dead_code_str)];
let allow_dead_code_item = attr::mk_list_item(allow_str, word_vec);
- let allow_dead_code = attr::mk_attr_outer(attr::mk_attr_id(),
+ let allow_dead_code = attr::mk_attr_outer(DUMMY_SP,
+ attr::mk_attr_id(),
allow_dead_code_item);
ast::Item {
fn visit_mac(&mut self, _mac: &Mac) {}
}
-pub struct CustomDerive {
+pub struct ProcMacroDerive {
inner: fn(TokenStream) -> TokenStream,
attrs: Vec<ast::Name>,
}
-impl CustomDerive {
- pub fn new(inner: fn(TokenStream) -> TokenStream, attrs: Vec<ast::Name>) -> CustomDerive {
- CustomDerive { inner: inner, attrs: attrs }
+impl ProcMacroDerive {
+ pub fn new(inner: fn(TokenStream) -> TokenStream, attrs: Vec<ast::Name>) -> ProcMacroDerive {
+ ProcMacroDerive { inner: inner, attrs: attrs }
}
}
-impl MultiItemModifier for CustomDerive {
+impl MultiItemModifier for ProcMacroDerive {
fn expand(&self,
ecx: &mut ExtCtxt,
span: Span,
Annotatable::Item(item) => item,
Annotatable::ImplItem(_) |
Annotatable::TraitItem(_) => {
- ecx.span_err(span, "custom derive attributes may only be \
+ ecx.span_err(span, "proc-macro derives may only be \
applied to struct/enum items");
return Vec::new()
}
ItemKind::Struct(..) |
ItemKind::Enum(..) => {},
_ => {
- ecx.span_err(span, "custom derive attributes may only be \
+ ecx.span_err(span, "proc-macro derives may only be \
applied to struct/enum items");
return Vec::new()
}
let stream = match res {
Ok(stream) => stream,
Err(e) => {
- let msg = "custom derive attribute panicked";
+ let msg = "proc-macro derive panicked";
let mut err = ecx.struct_span_fatal(span, msg);
if let Some(s) = e.downcast_ref::<String>() {
err.help(&format!("message: {}", s));
Ok(new_items) => new_items,
Err(_) => {
// FIXME: handle this better
- let msg = "custom derive produced unparseable tokens";
+ let msg = "proc-macro derive produced unparseable tokens";
ecx.struct_span_fatal(span, msg).emit();
panic!(FatalError);
}
use deriving;
use deriving::generic::*;
use deriving::generic::ty::*;
+use deriving::warn_if_deprecated;
use syntax::ast;
use syntax::ast::{Expr, MetaItem, Mutability};
mitem: &MetaItem,
item: &Annotatable,
push: &mut FnMut(Annotatable)) {
+ warn_if_deprecated(cx, span, "Decodable");
expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize")
}
use deriving;
use deriving::generic::*;
use deriving::generic::ty::*;
+use deriving::warn_if_deprecated;
use syntax::ast::{Expr, ExprKind, MetaItem, Mutability};
use syntax::ext::base::{Annotatable, ExtCtxt};
mitem: &MetaItem,
item: &Annotatable,
push: &mut FnMut(Annotatable)) {
+ warn_if_deprecated(cx, span, "Encodable");
expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize")
}
//! The compiler code necessary to implement the `#[derive]` extensions.
-use syntax::ast::{self, MetaItem};
-use syntax::attr::HasAttrs;
+use std::rc::Rc;
+use syntax::ast;
use syntax::codemap;
-use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension};
+use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver};
use syntax::ext::build::AstBuilder;
-use syntax::feature_gate;
use syntax::ptr::P;
use syntax::symbol::Symbol;
use syntax_pos::Span;
}
}
-pub fn expand_derive(cx: &mut ExtCtxt,
- span: Span,
- mitem: &MetaItem,
- annotatable: Annotatable)
- -> Vec<Annotatable> {
- debug!("expand_derive: span = {:?}", span);
- debug!("expand_derive: mitem = {:?}", mitem);
- debug!("expand_derive: annotatable input = {:?}", annotatable);
- let mut item = match annotatable {
- Annotatable::Item(item) => item,
- other => {
- cx.span_err(span, "`derive` can only be applied to items");
- return vec![other]
- }
- };
-
- let derive = Symbol::intern("derive");
- let mut derive_attrs = Vec::new();
- item = item.map_attrs(|attrs| {
- let partition = attrs.into_iter().partition(|attr| attr.name() == derive);
- derive_attrs = partition.0;
- partition.1
- });
-
- // Expand `#[derive]`s after other attribute macro invocations.
- if cx.resolver.find_attr_invoc(&mut item.attrs.clone()).is_some() {
- return vec![Annotatable::Item(item.map_attrs(|mut attrs| {
- attrs.push(cx.attribute(span, mitem.clone()));
- attrs.extend(derive_attrs);
- attrs
- }))];
- }
-
- let get_traits = |mitem: &MetaItem, cx: &ExtCtxt| {
- if mitem.value_str().is_some() {
- cx.span_err(mitem.span, "unexpected value in `derive`");
- }
-
- let traits = mitem.meta_item_list().unwrap_or(&[]).to_owned();
- if traits.is_empty() {
- cx.span_warn(mitem.span, "empty trait list in `derive`");
- }
- traits
- };
-
- let mut traits = get_traits(mitem, cx);
- for derive_attr in derive_attrs {
- traits.extend(get_traits(&derive_attr.value, cx));
- }
-
- // First, weed out malformed #[derive]
- traits.retain(|titem| {
- if titem.word().is_none() {
- cx.span_err(titem.span, "malformed `derive` entry");
- false
- } else {
- true
- }
- });
-
- // Next, check for old-style #[derive(Foo)]
- //
- // These all get expanded to `#[derive_Foo]` and will get expanded first. If
- // we actually add any attributes here then we return to get those expanded
- // and then eventually we'll come back to finish off the other derive modes.
- let mut new_attributes = Vec::new();
- traits.retain(|titem| {
- let tword = titem.word().unwrap();
- let tname = tword.name();
-
- if is_builtin_trait(tname) || {
- let derive_mode = ast::Path::from_ident(titem.span, ast::Ident::with_empty_ctxt(tname));
- cx.resolver.resolve_macro(cx.current_expansion.mark, &derive_mode, false).map(|ext| {
- if let SyntaxExtension::CustomDerive(_) = *ext { true } else { false }
- }).unwrap_or(false)
- } {
- return true;
- }
-
- if !cx.ecfg.enable_custom_derive() {
- feature_gate::emit_feature_err(&cx.parse_sess,
- "custom_derive",
- titem.span,
- feature_gate::GateIssue::Language,
- feature_gate::EXPLAIN_CUSTOM_DERIVE);
- } else {
- let name = Symbol::intern(&format!("derive_{}", tname));
- if !cx.resolver.is_whitelisted_legacy_custom_derive(name) {
- cx.span_warn(titem.span, feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE);
- }
- let mitem = cx.meta_word(titem.span, name);
- new_attributes.push(cx.attribute(mitem.span, mitem));
- }
- false
- });
- if new_attributes.len() > 0 {
- item = item.map(|mut i| {
- i.attrs.extend(new_attributes);
- if traits.len() > 0 {
- let list = cx.meta_list(mitem.span, derive, traits);
- i.attrs.push(cx.attribute(mitem.span, list));
- }
- i
- });
- return vec![Annotatable::Item(item)]
- }
-
- // Now check for macros-1.1 style custom #[derive].
- //
- // Expand each of them in order given, but *before* we expand any built-in
- // derive modes. The logic here is to:
- //
- // 1. Collect the remaining `#[derive]` annotations into a list. If
- // there are any left, attach a `#[derive]` attribute to the item
- // that we're currently expanding with the remaining derive modes.
- // 2. Manufacture a `#[derive(Foo)]` attribute to pass to the expander.
- // 3. Expand the current item we're expanding, getting back a list of
- // items that replace it.
- // 4. Extend the returned list with the current list of items we've
- // collected so far.
- // 5. Return everything!
- //
- // If custom derive extensions end up threading through the `#[derive]`
- // attribute, we'll get called again later on to continue expanding
- // those modes.
- let macros_11_derive = traits.iter()
- .cloned()
- .enumerate()
- .filter(|&(_, ref name)| !is_builtin_trait(name.name().unwrap()))
- .next();
- if let Some((i, titem)) = macros_11_derive {
- let tname = ast::Ident::with_empty_ctxt(titem.name().unwrap());
- let path = ast::Path::from_ident(titem.span, tname);
- let ext = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false).unwrap();
-
- traits.remove(i);
- if traits.len() > 0 {
- item = item.map(|mut i| {
- let list = cx.meta_list(mitem.span, derive, traits);
- i.attrs.push(cx.attribute(mitem.span, list));
- i
- });
- }
- let titem = cx.meta_list_item_word(titem.span, titem.name().unwrap());
- let mitem = cx.meta_list(titem.span, derive, vec![titem]);
- let item = Annotatable::Item(item);
-
- let span = Span {
- expn_id: cx.codemap().record_expansion(codemap::ExpnInfo {
- call_site: mitem.span,
- callee: codemap::NameAndSpan {
- format: codemap::MacroAttribute(Symbol::intern(&format!("derive({})", tname))),
- span: None,
- allow_internal_unstable: false,
- },
- }),
- ..mitem.span
- };
-
- if let SyntaxExtension::CustomDerive(ref ext) = *ext {
- return ext.expand(cx, span, &mitem, item);
- } else {
- unreachable!()
- }
- }
-
- // Ok, at this point we know that there are no old-style `#[derive_Foo]` nor
- // any macros-1.1 style `#[derive(Foo)]`. Expand all built-in traits here.
-
- // RFC #1445. `#[derive(PartialEq, Eq)]` adds a (trusted)
- // `#[structural_match]` attribute.
- let (partial_eq, eq) = (Symbol::intern("PartialEq"), Symbol::intern("Eq"));
- if traits.iter().any(|t| t.name() == Some(partial_eq)) &&
- traits.iter().any(|t| t.name() == Some(eq)) {
- let structural_match = Symbol::intern("structural_match");
- let span = allow_unstable(cx, span, "derive(PartialEq, Eq)");
- let meta = cx.meta_word(span, structural_match);
- item = item.map(|mut i| {
- i.attrs.push(cx.attribute(span, meta));
- i
- });
- }
-
- // RFC #1521. `Clone` can assume that `Copy` types' clone implementation is
- // the same as the copy implementation.
- //
- // Add a marker attribute here picked up during #[derive(Clone)]
- let (copy, clone) = (Symbol::intern("Copy"), Symbol::intern("Clone"));
- if traits.iter().any(|t| t.name() == Some(clone)) &&
- traits.iter().any(|t| t.name() == Some(copy)) {
- let marker = Symbol::intern("rustc_copy_clone_marker");
- let span = allow_unstable(cx, span, "derive(Copy, Clone)");
- let meta = cx.meta_word(span, marker);
- item = item.map(|mut i| {
- i.attrs.push(cx.attribute(span, meta));
- i
- });
- }
-
- let mut items = Vec::new();
- for titem in traits.iter() {
- let tname = titem.word().unwrap().name();
- let name = Symbol::intern(&format!("derive({})", tname));
- let mitem = cx.meta_word(titem.span, name);
-
- let span = Span {
- expn_id: cx.codemap().record_expansion(codemap::ExpnInfo {
- call_site: titem.span,
- callee: codemap::NameAndSpan {
- format: codemap::MacroAttribute(name),
- span: None,
- allow_internal_unstable: true,
- },
- }),
- ..titem.span
- };
-
- let my_item = Annotatable::Item(item);
- expand_builtin(&tname.as_str(), cx, span, &mitem, &my_item, &mut |a| {
- items.push(a);
- });
- item = my_item.expect_item();
- }
-
- items.insert(0, Annotatable::Item(item));
- return items
-}
-
macro_rules! derive_traits {
($( $name:expr => $func:path, )+) => {
pub fn is_builtin_trait(name: ast::Name) -> bool {
}
}
- fn expand_builtin(name: &str,
- ecx: &mut ExtCtxt,
- span: Span,
- mitem: &MetaItem,
- item: &Annotatable,
- push: &mut FnMut(Annotatable)) {
- match name {
- $(
- $name => {
- warn_if_deprecated(ecx, span, $name);
- $func(ecx, span, mitem, item, push);
- }
- )*
- _ => panic!("not a builtin derive mode: {}", name),
- }
+ pub fn register_builtin_derives(resolver: &mut Resolver) {
+ $(
+ resolver.add_ext(
+ ast::Ident::with_empty_ctxt(Symbol::intern($name)),
+ Rc::new(SyntaxExtension::BuiltinDerive($func))
+ );
+ )*
}
}
}
#![feature(staged_api)]
extern crate fmt_macros;
-#[macro_use]
extern crate log;
#[macro_use]
extern crate syntax;
use std::rc::Rc;
use syntax::ast;
-use syntax::ext::base::{MacroExpanderFn, NormalTT, MultiModifier, NamedSyntaxExtension};
+use syntax::ext::base::{MacroExpanderFn, NormalTT, NamedSyntaxExtension};
use syntax::symbol::Symbol;
pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
user_exts: Vec<NamedSyntaxExtension>,
enable_quotes: bool) {
+ deriving::register_builtin_derives(resolver);
+
let mut register = |name, ext| {
resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext));
};
register(Symbol::intern("format_args"),
NormalTT(Box::new(format::expand_format_args), None, true));
- register(Symbol::intern("derive"), MultiModifier(Box::new(deriving::expand_derive)));
-
for (name, ext) in user_exts {
register(name, ext);
}
use deriving;
-struct CustomDerive {
+struct ProcMacroDerive {
trait_name: ast::Name,
function_name: Ident,
span: Span,
}
struct CollectProcMacros<'a> {
- derives: Vec<CustomDerive>,
+ derives: Vec<ProcMacroDerive>,
attr_macros: Vec<AttrProcMacro>,
in_root: bool,
handler: &'a errors::Handler,
};
if self.in_root && item.vis == ast::Visibility::Public {
- self.derives.push(CustomDerive {
+ self.derives.push(ProcMacroDerive {
span: item.span,
trait_name: trait_name,
function_name: item.ident,
// }
// }
fn mk_registrar(cx: &mut ExtCtxt,
- custom_derives: &[CustomDerive],
+ custom_derives: &[ProcMacroDerive],
custom_attrs: &[AttrProcMacro]) -> P<ast::Item> {
let eid = cx.codemap().record_expansion(ExpnInfo {
call_site: DUMMY_SP,
/// the error, and would be rendered with `^^^`.
/// - they can have a *label*. In this case, the label is written next
/// to the mark in the snippet when we render.
-#[derive(Clone, Debug, Hash, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub struct MultiSpan {
primary_spans: Vec<Span>,
span_labels: Vec<(Span, String)>,
-Subproject commit a3736a0a1907cbc8bf619708738815a5fd789c80
+Subproject commit da282f1bb7277b4d30fa1599ee29ad8eb4dd2a92
[package]
name = "std_shim"
-version = "0.1.0"
+version = "0.0.0"
authors = ["The Rust Project Developers"]
[lib]
[package]
name = "test_shim"
-version = "0.1.0"
+version = "0.0.0"
authors = ["The Rust Project Developers"]
[lib]
}
#endif
+#if LLVM_VERSION_GE(4, 0)
+ return wrap(Builder->createGlobalVariableExpression(
+#else
return wrap(Builder->createGlobalVariable(
+#endif
unwrapDI<DIDescriptor>(Context), Name, LinkageName,
unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
#if LLVM_VERSION_GE(4, 0)
#endif
}
-extern "C" void LLVMRustSetPersonalityFn(LLVMBuilderRef B,
- LLVMValueRef Personality) {
-#if LLVM_VERSION_GE(3, 8)
- unwrap(B)->GetInsertBlock()->getParent()->setPersonalityFn(
- cast<Function>(unwrap(Personality)));
-#endif
-}
-
#if LLVM_VERSION_GE(3, 8)
extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
LLVMValueRef *Inputs,
# tarball for a stable release you'll likely see `1.x.0-$date` where `1.x.0` was
# released on `$date`
-rustc: beta-2016-12-20
+rustc: beta-2017-02-01
cargo: bfee18f73287687c543bda8c35e4e33808792715
reg.register_macro("identity", expand_identity);
reg.register_syntax_extension(
Symbol::intern("into_multi_foo"),
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
MultiModifier(Box::new(expand_into_foo_multi)));
reg.register_syntax_extension(
Symbol::intern("duplicate"),
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
MultiDecorator(Box::new(expand_duplicate)));
}
fn main() {
// Okay
let Record { .. } = Record::new();
- // Okay (for now; see RFC Issue #902)
- let Tuple(..) = Tuple::new();
// Okay
let Record { a_stable_pub: _, a_unstable_declared_pub: _, .. } = Record::new();
- // Okay (for now; see RFC Issue #902)
- let Tuple(_, _, ..) = Tuple::new(); // analogous to above
let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } =
Record::new();
//~^^ ERROR use of unstable library feature 'unstable_undeclared'
- let Tuple(_, _, _, ..) = Tuple::new(); // analogous to previous
- //~^ ERROR use of unstable library feature 'unstable_undeclared'
-
let r = Record::new();
let t = Tuple::new();
#[derive(
A
)]
-//~^^ ERROR: custom derive produced unparseable tokens
+//~^^ ERROR: proc-macro derive produced unparseable tokens
struct A;
fn main() {}
extern crate derive_panic;
#[derive(A)]
-//~^ ERROR: custom derive attribute panicked
+//~^ ERROR: proc-macro derive panicked
//~| HELP: message: nope!
struct Foo;
#![feature(rustc_attrs)]
extern crate derive_a;
-//~^ WARN custom derive crates and `#[no_link]` crates have no effect without `#[macro_use]`
+//~^ WARN proc macro crates and `#[no_link]` crates have no effect without `#[macro_use]`
#[rustc_error]
fn main() {} //~ ERROR compilation successful
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-mod Bar {
- pub struct Foo( bool, pub i32, f32, bool);
- //~^ NOTE private field declared here
- //~| NOTE private field declared here
- //~| NOTE private field declared here
-}
-
-fn main() {
- let f = Bar::Foo(false,1,0.1, true); //~ ERROR E0450
- //~^ NOTE cannot construct with a private field
-}
//~^ NOTE field `b` is private
}
-fn pat_match_tuple(foo: Bar::FooTuple) {
- let Bar::FooTuple(a,b) = foo; //~ ERROR E0451
- //~^ NOTE field `1` is private
-}
-
fn main() {
let f = Bar::Foo{ a: 0, b: 0 }; //~ ERROR E0451
//~^ NOTE field `b` is private
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test was derived from the wasm and parsell crates. They
+// stopped compiling when #32330 is fixed.
+
+#![allow(dead_code, unused_variables)]
+
+use std::str::Chars;
+
+pub trait HasOutput<Ch, Str> {
+ type Output;
+}
+
+#[derive(Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Debug)]
+pub enum Token<'a> {
+ Begin(&'a str)
+}
+
+fn mk_unexpected_char_err<'a>() -> Option<&'a i32> {
+ unimplemented!()
+}
+
+fn foo<'a>(data: &mut Chars<'a>) {
+ bar(mk_unexpected_char_err)
+}
+
+fn bar<F>(t: F)
+ // No type can satisfy this requirement, since `'a` does not
+ // appear in any of the input types:
+ where F: for<'a> Fn() -> Option<&'a i32>
+ //~^ ERROR E0582
+{
+}
+
+fn baz<F>(t: F)
+ // No type can satisfy this requirement, since `'a` does not
+ // appear in any of the input types:
+ where F: for<'a> Iterator<Item=&'a i32>
+ //~^ ERROR E0582
+{
+}
+
+fn main() {
+}
#![allow(dead_code)]
#![feature(rustc_attrs)]
-#![deny(hr_lifetime_in_assoc_type)]
+#![allow(hr_lifetime_in_assoc_type)]
trait Foo<'a> {
type Item;
// Check that appearing in a projection input in the argument is not enough:
#[cfg(func)]
fn func1(_: for<'a> fn(<() as Foo<'a>>::Item) -> &'a i32) {
- //[func]~^ ERROR return type references lifetime `'a`
- //[func]~| WARNING previously accepted
+ //[func]~^ ERROR E0581
}
// Check that appearing in a projection input in the return still
// causes an error:
#[cfg(func)]
fn func2(_: for<'a> fn() -> <() as Foo<'a>>::Item) {
- //[func]~^ ERROR return type references lifetime `'a`
- //[func]~| WARNING previously accepted
+ //[func]~^ ERROR E0581
}
#[cfg(object)]
fn object1(_: Box<for<'a> Fn(<() as Foo<'a>>::Item) -> &'a i32>) {
- //[object]~^ ERROR `Output` references lifetime `'a`
- //[object]~| WARNING previously accepted
+ //[object]~^ ERROR E0582
}
#[cfg(object)]
fn object2(_: Box<for<'a> Fn() -> <() as Foo<'a>>::Item>) {
- //[object]~^ ERROR `Output` references lifetime `'a`
- //[object]~| WARNING previously accepted
+ //[object]~^ ERROR E0582
}
#[cfg(clause)]
fn clause1<T>() where T: for<'a> Fn(<() as Foo<'a>>::Item) -> &'a i32 {
//[clause]~^ ERROR `Output` references lifetime `'a`
- //[clause]~| WARNING previously accepted
}
#[cfg(clause)]
fn clause2<T>() where T: for<'a> Fn() -> <() as Foo<'a>>::Item {
//[clause]~^ ERROR `Output` references lifetime `'a`
- //[clause]~| WARNING previously accepted
}
#[rustc_error]
#![allow(dead_code)]
#![feature(rustc_attrs)]
#![feature(unboxed_closures)]
-#![deny(hr_lifetime_in_assoc_type)]
trait Foo {
type Item;
#[cfg(angle)]
fn angle<T: for<'a> Foo<Item=&'a i32>>() {
//[angle]~^ ERROR binding for associated type `Item` references lifetime `'a`
- //[angle]~| WARNING previously accepted
}
#[cfg(angle)]
fn angle1<T>() where T: for<'a> Foo<Item=&'a i32> {
//[angle]~^ ERROR binding for associated type `Item` references lifetime `'a`
- //[angle]~| WARNING previously accepted
}
#[cfg(angle)]
fn angle2<T>() where for<'a> T: Foo<Item=&'a i32> {
//[angle]~^ ERROR binding for associated type `Item` references lifetime `'a`
- //[angle]~| WARNING previously accepted
}
#[cfg(angle)]
fn angle3(_: &for<'a> Foo<Item=&'a i32>) {
//[angle]~^ ERROR binding for associated type `Item` references lifetime `'a`
- //[angle]~| WARNING previously accepted
}
#[cfg(paren)]
fn paren<T: for<'a> Fn() -> &'a i32>() {
//[paren]~^ ERROR binding for associated type `Output` references lifetime `'a`
- //[paren]~| WARNING previously accepted
}
#[cfg(paren)]
fn paren1<T>() where T: for<'a> Fn() -> &'a i32 {
//[paren]~^ ERROR binding for associated type `Output` references lifetime `'a`
- //[paren]~| WARNING previously accepted
}
#[cfg(paren)]
fn paren2<T>() where for<'a> T: Fn() -> &'a i32 {
//[paren]~^ ERROR binding for associated type `Output` references lifetime `'a`
- //[paren]~| WARNING previously accepted
}
#[cfg(paren)]
fn paren3(_: &for<'a> Fn() -> &'a i32) {
//[paren]~^ ERROR binding for associated type `Output` references lifetime `'a`
- //[paren]~| WARNING previously accepted
}
#[cfg(elision)]
#[cfg(sig)]
fn sig1(_: for<'a> fn() -> &'a i32) {
//[sig]~^ ERROR return type references lifetime `'a`
- //[sig]~| WARNING previously accepted
}
#[cfg(sig)]
fn sig2(_: for<'a, 'b> fn(&'b i32) -> &'a i32) {
//[sig]~^ ERROR return type references lifetime `'a`
- //[sig]~| WARNING previously accepted
}
#[cfg(local)]
fn local1() {
let _: for<'a> fn() -> &'a i32 = loop { };
//[local]~^ ERROR return type references lifetime `'a`
- //[local]~| WARNING previously accepted
}
#[cfg(structure)]
struct Struct1 {
x: for<'a> fn() -> &'a i32
//[structure]~^ ERROR return type references lifetime `'a`
- //[structure]~| WARNING previously accepted
}
#[cfg(elision)]
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This test was derived from the wasm and parsell crates. They
-// stopped compiling when #32330 is fixed.
-
-#![allow(dead_code, unused_variables)]
-#![deny(hr_lifetime_in_assoc_type)]
-
-use std::str::Chars;
-
-pub trait HasOutput<Ch, Str> {
- type Output;
-}
-
-#[derive(Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Debug)]
-pub enum Token<'a> {
- Begin(&'a str)
-}
-
-fn mk_unexpected_char_err<'a>() -> Option<&'a i32> {
- unimplemented!()
-}
-
-fn foo<'a>(data: &mut Chars<'a>) {
- bar(mk_unexpected_char_err)
- //~^ ERROR lifetime parameter `'a` declared on fn `mk_unexpected_char_err`
- //~| WARNING hard error in a future release
-}
-
-fn bar<F>(t: F)
- // No type can satisfy this requirement, since `'a` does not
- // appear in any of the input types:
- where F: for<'a> Fn() -> Option<&'a i32>
- //~^ ERROR associated type `Output` references lifetime `'a`, which does not
- //~| WARNING hard error in a future release
-{
-}
-
-fn main() {
-}
fn main() {
let tmp: Box<_>;
let mut buggy_map: HashMap<usize, &usize> = HashMap::new();
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
buggy_map.insert(42, &*Box::new(1)); //~ ERROR borrowed value does not live long enough
// but it is ok if we use a temporary
impl Trait for Foo {}
pub fn main() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let x: Box<Trait> = Box::new(Foo);
let _y: &Trait = x; //~ ERROR mismatched types
//~| expected type `&Trait`
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(dead_code)]
+#![allow(unreachable_code)]
+#![deny(resolve_trait_on_defaulted_unit)]
+
+trait Deserialize: Sized {
+ fn deserialize() -> Result<Self, String>;
+}
+
+impl Deserialize for () {
+ fn deserialize() -> Result<(), String> {
+ Ok(())
+ }
+}
+
+fn doit() -> Result<(), String> {
+ let _ = match Deserialize::deserialize() {
+ //~^ ERROR code relies on type
+ //~| WARNING previously accepted
+ Ok(x) => x,
+ Err(e) => return Err(e),
+ };
+ Ok(())
+}
+
+trait ImplementedForUnitButNotNever {}
+
+impl ImplementedForUnitButNotNever for () {}
+
+fn foo<T: ImplementedForUnitButNotNever>(_t: T) {}
+
+fn smeg() {
+ let _x = return;
+ foo(_x);
+ //~^ ERROR code relies on type
+ //~| WARNING previously accepted
+}
+
+fn main() {
+ let _ = doit();
+}
+
// ignore-tidy-linelength
#[derive(Eqr)]
-//~^ ERROR `#[derive]` for custom traits is not stable enough for use. It is deprecated and will be removed in v1.15 (see issue #29644)
+//~^ ERROR cannot find derive macro `Eqr` in this scope
struct Foo;
pub fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#[derive(FromPrimitive)] //~ERROR `#[derive]` for custom traits is not stable
+#[derive(FromPrimitive)] //~ERROR cannot find derive macro `FromPrimitive` in this scope
enum Foo {}
fn main() {}
pub fn main() {
// Assignment.
let f5: &mut Fat<ToBar> = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let z: Box<ToBar> = Box::new(Bar1 {f: 36});
f5.ptr = *z;
//~^ ERROR `ToBar: std::marker::Sized` is not satisfied
pub fn main() {
// Assignment.
let f5: &mut Fat<ToBar> = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let z: Box<ToBar> = Box::new(Bar1 {f: 36});
f5.ptr = Bar1 {f: 36};
//~^ ERROR mismatched types
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[link(name="foo", kind="static-nobundle")]
+//~^ ERROR: kind="static-nobundle" is feature gated
+extern {}
//~^ WARN `Foo` is ambiguous
//~| WARN hard error in a future release
//~| NOTE see issue #38260
+ //~| NOTE #[warn(legacy_imports)] on by default
}
}
// except according to those terms.
fn test<'x>(x: &'x isize) {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
drop::<Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
x //~ ERROR E0312
}));
}
fn main() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let closure: Box<Fn()+'static> = Box::new(|| ());
let test = box Test { func: closure }; //~ ERROR mismatched types
}
fn main() {
let &v = new();
- //~^ ERROR unable to infer enough type information about `_` [E0282]
+ //~^ ERROR type annotations needed [E0282]
//~| NOTE cannot infer type for `_`
- //~| NOTE type annotations or generic parameter binding
}
fn main() {
let &v = new();
- //~^ ERROR unable to infer enough type information about `_` [E0282]
+ //~^ ERROR type annotations needed [E0282]
//~| NOTE cannot infer type for `_`
- //~| NOTE type annotations or generic parameter binding
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:type annotations or generic parameter binding required
+// error-pattern:type annotations needed
fn main() {
panic!(
std::default::Default::default()
//~^ ERROR cast to unsized type: `&[usize; 2]` as `[usize]`
//~^^ HELP consider using an implicit coercion to `&[usize]` instead
- // FIXME (#22405): Replace `std::boxed::Box::new` with `box` here when/if possible.
let _bar = Box::new(1_usize) as std::fmt::Debug;
//~^ ERROR cast to unsized type: `std::boxed::Box<usize>` as `std::fmt::Debug`
//~^^ HELP try casting to a `Box` instead
struct B<T>(marker::PhantomData<T>);
fn main() {
- let foo = B(marker::PhantomData); //~ ERROR unable to infer enough type information
+ let foo = B(marker::PhantomData); //~ ERROR type annotations needed
let closure = || foo;
}
// and rejected.
fn main() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
(|| Box::new(*(&[0][..])))();
//~^ ERROR `[{integer}]: std::marker::Sized` is not satisfied
}
// except according to those terms.
fn main() {
- let x; //~ ERROR unable to infer enough type information
+ let x; //~ ERROR type annotations needed
}
use std::cell::RefCell;
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-
fn main() {
let mut y = 1;
let c = RefCell::new(vec![]);
let b:Box<Any> = Box::new(bar as fn(_)->_);
b.downcast_ref::<fn(_)->_>(); //~ ERROR E0282
//~| NOTE cannot infer type for `_`
- //~| NOTE type annotations or generic parameter binding required
}
fn main() {
let ex = |x| {
- let_(add(x,x), |y| { //~ ERROR unable to infer enough type information about `VAR`
+ let_(add(x,x), |y| { //~ ERROR type annotations needed
let_(add(x, x), |x|x)})};
}
let a = 1;
let b = 2;
unsafe {swap::<&mut _>(transmute(&a), transmute(&b))};
- //~^ ERROR unable to infer enough type information about `_`
+ //~^ ERROR type annotations needed
}
// except according to those terms.
#![deny(warnings)] //~ NOTE: lint level defined here
-use std::thread; //~ ERROR: unused import
+use std::thread;
+//~^ ERROR: unused import
+//~| NOTE: #[deny(unused_imports)] implied by #[deny(warnings)]
fn main() {}
let _woohoo = (&my_struct).priv_field;
//~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let _woohoo = (Box::new(my_struct)).priv_field;
//~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
(&my_struct).happyfun(); //~ ERROR method `happyfun` is private
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
(Box::new(my_struct)).happyfun(); //~ ERROR method `happyfun` is private
let nope = my_struct.priv_field;
//~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
fn main() {
let Box(a) = loop { };
- //~^ ERROR field `0` of struct `std::boxed::Box` is private
+ //~^ ERROR expected tuple struct/variant, found struct `Box`
+ //~| ERROR expected tuple struct/variant, found struct `Box`
// (The below is a trick to allow compiler to infer a type for
// variable `a` without attempting to ascribe a type to the
fn id<T>(t: T) -> T { t }
fn f<'r, T>(v: &'r T) -> Box<FnMut() -> T + 'r> {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
id(Box::new(|| *v))
//~^ ERROR E0373
//~| NOTE `v` is borrowed here
// except according to those terms.
fn main() { format!("{:?}", None); }
- //~^ ERROR unable to infer enough type information about `T` [E0282]
+ //~^ ERROR type annotations needed [E0282]
fn main() {
// Unconstrained type:
format!("{:?}", None);
- //~^ ERROR unable to infer enough type information about `T` [E0282]
+ //~^ ERROR type annotations needed [E0282]
}
fn main() {
mem::transmute(0);
- //~^ ERROR unable to infer enough type information about `U` [E0282]
+ //~^ ERROR type annotations needed [E0282]
//~| NOTE cannot infer type for `U`
- //~| NOTE type annotations or generic parameter binding
}
pub fn bar() {
foo(TypeWithState(marker::PhantomData));
- //~^ ERROR unable to infer enough type information about `State` [E0282]
+ //~^ ERROR type annotations needed [E0282]
//~| NOTE cannot infer type for `State`
- //~| NOTE type annotations or generic parameter binding
}
fn main() {
fn main() {
let v = &[];
- let it = v.iter(); //~ ERROR unable to infer enough type information about `T` [E0282]
+ let it = v.iter(); //~ ERROR type annotations needed [E0282]
//~| NOTE cannot infer type for `T`
- //~| NOTE type annotations or generic parameter binding
+ //~| NOTE consider giving `it` a type
}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![deny(bad_style)]
-//~^ NOTE lint level defined here
-#![allow(dead_code)]
-
-fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name
-
-#[allow(bad_style)]
-mod test {
- fn CamelCase() {}
-
- #[forbid(bad_style)]
- //~^ NOTE lint level defined here
- //~^^ NOTE lint level defined here
- mod bad {
- fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name
-
- static bad: isize = 1; //~ ERROR static variable `bad` should have an upper case name
- }
-
- mod warn {
- #![warn(bad_style)]
- //~^ NOTE lint level defined here
- //~| NOTE lint level defined here
-
- fn CamelCase() {} //~ WARN function `CamelCase` should have a snake case name
-
- struct snake_case; //~ WARN type `snake_case` should have a camel case name
- }
-}
-
-fn main() {}
// compile-flags: -F unused_features
// aux-build:lint_output_format.rs
-#![feature(foo)] //~ ERROR unused or unknown feature
+#![feature(foo)]
+//~^ ERROR unused or unknown feature
+//~| NOTE requested on the command line with `-F unused-features`
#![feature(test_feature)]
extern crate lint_output_format;
use lint_output_format::{foo, bar};
-//~^ WARNING use of deprecated item: text,
+//~^ WARNING use of deprecated item: text
+//~| NOTE #[warn(deprecated)] on by default
fn main() {
- let _x = foo(); //~ WARNING #[warn(deprecated)] on by default
+ let _x = foo();
+ //~^ WARNING use of deprecated item: text
+ //~| NOTE #[warn(deprecated)] on by default
let _y = bar();
}
foo!(0); // Check that we report errors at macro definition, not expansion.
let _: cfg!(foo) = (); //~ ERROR non-type macro in type position
- derive!(); //~ ERROR `derive` can only be used in attributes
+ derive!(); //~ ERROR macro undefined: 'derive!'
}
#![feature(asm)]
#![feature(trace_macros, concat_idents)]
-#[derive(Default, //~ ERROR
- Zero)] //~ ERROR
-enum CantDeriveThose {}
+#[derive(Zero)] //~ ERROR
+struct CantDeriveThis;
+
+#[derive(Default)] //~ ERROR
+enum OrDeriveThis {}
fn main() {
doesnt_exist!(); //~ ERROR
fn main() {
let x: Box<HashMap<isize, isize>> = box HashMap::new();
let x: Box<Map<isize, isize>> = x;
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let y: Box<Map<usize, isize>> = Box::new(x);
//~^ ERROR `std::boxed::Box<Map<isize, isize>>: Map<usize, isize>` is not satisfied
}
fn m1() {
// we couldn't infer the type of the vector just based on calling foo()...
let mut x = Vec::new();
- //~^ ERROR unable to infer enough type information about `T` [E0282]
+ //~^ ERROR type annotations needed [E0282]
x.foo();
}
{
if (foo)
bar; //~ ERROR expected `{`, found `bar`
- //^ HELP try placing this code inside a block
+ //~^ HELP try placing this code inside a block
+ //~| SUGGESTION { bar; }
}
}
}
fn conspirator<F>(mut f: F) where F: FnMut(&mut R, bool) {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let mut r = R {c: Box::new(f)};
f(&mut r, false) //~ ERROR use of moved value
}
#[no_link]
extern crate empty_struct;
-//~^ WARN custom derive crates and `#[no_link]` crates have no effect without `#[macro_use]`
+//~^ WARN proc macro crates and `#[no_link]` crates have no effect without `#[macro_use]`
fn main() {
empty_struct::XEmpty1; //~ ERROR cannot find value `XEmpty1` in module `empty_struct`
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(unused)]
+
+use m::S;
+
+mod m {
+ pub struct S(u8);
+
+ mod n {
+ use S;
+ fn f() {
+ S(10);
+ //~^ ERROR private struct constructors are not usable through reexports in outer modules
+ //~| WARN this was previously accepted
+ }
+ }
+}
+
+fn main() {}
}
fn this_crate() {
- let a = a::A(()); //~ ERROR: cannot invoke tuple struct constructor
- let b = a::B(2); //~ ERROR: cannot invoke tuple struct constructor
- let c = a::C(2, 3); //~ ERROR: cannot invoke tuple struct constructor
+ let a = a::A(()); //~ ERROR tuple struct `A` is private
+ let b = a::B(2); //~ ERROR tuple struct `B` is private
+ let c = a::C(2, 3); //~ ERROR tuple struct `C` is private
let d = a::D(4);
- let a::A(()) = a; //~ ERROR: field `0` of struct `a::A` is private
- let a::A(_) = a;
- match a { a::A(()) => {} } //~ ERROR: field `0` of struct `a::A` is private
- match a { a::A(_) => {} }
-
- let a::B(_) = b;
- let a::B(_b) = b; //~ ERROR: field `0` of struct `a::B` is private
- match b { a::B(_) => {} }
- match b { a::B(_b) => {} } //~ ERROR: field `0` of struct `a::B` is private
- match b { a::B(1) => {} a::B(_) => {} } //~ ERROR: field `0` of struct `a::B` is private
-
- let a::C(_, _) = c;
- let a::C(_a, _) = c;
- let a::C(_, _b) = c; //~ ERROR: field `1` of struct `a::C` is private
- let a::C(_a, _b) = c; //~ ERROR: field `1` of struct `a::C` is private
- match c { a::C(_, _) => {} }
- match c { a::C(_a, _) => {} }
- match c { a::C(_, _b) => {} } //~ ERROR: field `1` of struct `a::C` is private
- match c { a::C(_a, _b) => {} } //~ ERROR: field `1` of struct `a::C` is private
+ let a::A(()) = a; //~ ERROR tuple struct `A` is private
+ let a::A(_) = a; //~ ERROR tuple struct `A` is private
+ match a { a::A(()) => {} } //~ ERROR tuple struct `A` is private
+ match a { a::A(_) => {} } //~ ERROR tuple struct `A` is private
+
+ let a::B(_) = b; //~ ERROR tuple struct `B` is private
+ let a::B(_b) = b; //~ ERROR tuple struct `B` is private
+ match b { a::B(_) => {} } //~ ERROR tuple struct `B` is private
+ match b { a::B(_b) => {} } //~ ERROR tuple struct `B` is private
+ match b { a::B(1) => {} a::B(_) => {} } //~ ERROR tuple struct `B` is private
+ //~^ ERROR tuple struct `B` is private
+
+ let a::C(_, _) = c; //~ ERROR tuple struct `C` is private
+ let a::C(_a, _) = c; //~ ERROR tuple struct `C` is private
+ let a::C(_, _b) = c; //~ ERROR tuple struct `C` is private
+ let a::C(_a, _b) = c; //~ ERROR tuple struct `C` is private
+ match c { a::C(_, _) => {} } //~ ERROR tuple struct `C` is private
+ match c { a::C(_a, _) => {} } //~ ERROR tuple struct `C` is private
+ match c { a::C(_, _b) => {} } //~ ERROR tuple struct `C` is private
+ match c { a::C(_a, _b) => {} } //~ ERROR tuple struct `C` is private
let a::D(_) = d;
let a::D(_d) = d;
match d { a::D(_d) => {} }
match d { a::D(1) => {} a::D(_) => {} }
- let a2 = a::A; //~ ERROR: cannot invoke tuple struct constructor
- let b2 = a::B; //~ ERROR: cannot invoke tuple struct constructor
- let c2 = a::C; //~ ERROR: cannot invoke tuple struct constructor
+ let a2 = a::A; //~ ERROR tuple struct `A` is private
+ let b2 = a::B; //~ ERROR tuple struct `B` is private
+ let c2 = a::C; //~ ERROR tuple struct `C` is private
let d2 = a::D;
}
fn xcrate() {
- let a = other::A(()); //~ ERROR: cannot invoke tuple struct constructor
- let b = other::B(2); //~ ERROR: cannot invoke tuple struct constructor
- let c = other::C(2, 3); //~ ERROR: cannot invoke tuple struct constructor
+ let a = other::A(()); //~ ERROR tuple struct `A` is private
+ let b = other::B(2); //~ ERROR tuple struct `B` is private
+ let c = other::C(2, 3); //~ ERROR tuple struct `C` is private
let d = other::D(4);
- let other::A(()) = a; //~ ERROR: field `0` of struct `other::A` is private
- let other::A(_) = a;
- match a { other::A(()) => {} }
- //~^ ERROR: field `0` of struct `other::A` is private
- match a { other::A(_) => {} }
-
- let other::B(_) = b;
- let other::B(_b) = b; //~ ERROR: field `0` of struct `other::B` is private
- match b { other::B(_) => {} }
- match b { other::B(_b) => {} }
- //~^ ERROR: field `0` of struct `other::B` is private
- match b { other::B(1) => {} other::B(_) => {} }
- //~^ ERROR: field `0` of struct `other::B` is private
-
- let other::C(_, _) = c;
- let other::C(_a, _) = c;
- let other::C(_, _b) = c; //~ ERROR: field `1` of struct `other::C` is private
- let other::C(_a, _b) = c; //~ ERROR: field `1` of struct `other::C` is private
- match c { other::C(_, _) => {} }
- match c { other::C(_a, _) => {} }
- match c { other::C(_, _b) => {} }
- //~^ ERROR: field `1` of struct `other::C` is private
- match c { other::C(_a, _b) => {} }
- //~^ ERROR: field `1` of struct `other::C` is private
+ let other::A(()) = a; //~ ERROR tuple struct `A` is private
+ let other::A(_) = a; //~ ERROR tuple struct `A` is private
+ match a { other::A(()) => {} } //~ ERROR tuple struct `A` is private
+ match a { other::A(_) => {} } //~ ERROR tuple struct `A` is private
+
+ let other::B(_) = b; //~ ERROR tuple struct `B` is private
+ let other::B(_b) = b; //~ ERROR tuple struct `B` is private
+ match b { other::B(_) => {} } //~ ERROR tuple struct `B` is private
+ match b { other::B(_b) => {} } //~ ERROR tuple struct `B` is private
+ match b { other::B(1) => {} other::B(_) => {} } //~ ERROR tuple struct `B` is private
+ //~^ ERROR tuple struct `B` is private
+
+ let other::C(_, _) = c; //~ ERROR tuple struct `C` is private
+ let other::C(_a, _) = c; //~ ERROR tuple struct `C` is private
+ let other::C(_, _b) = c; //~ ERROR tuple struct `C` is private
+ let other::C(_a, _b) = c; //~ ERROR tuple struct `C` is private
+ match c { other::C(_, _) => {} } //~ ERROR tuple struct `C` is private
+ match c { other::C(_a, _) => {} } //~ ERROR tuple struct `C` is private
+ match c { other::C(_, _b) => {} } //~ ERROR tuple struct `C` is private
+ match c { other::C(_a, _b) => {} } //~ ERROR tuple struct `C` is private
let other::D(_) = d;
let other::D(_d) = d;
match d { other::D(_d) => {} }
match d { other::D(1) => {} other::D(_) => {} }
- let a2 = other::A; //~ ERROR: cannot invoke tuple struct constructor
- let b2 = other::B; //~ ERROR: cannot invoke tuple struct constructor
- let c2 = other::C; //~ ERROR: cannot invoke tuple struct constructor
+ let a2 = other::A; //~ ERROR tuple struct `A` is private
+ let b2 = other::B; //~ ERROR tuple struct `B` is private
+ let c2 = other::C; //~ ERROR tuple struct `C` is private
let d2 = other::D;
}
trait Foo {}
impl<'a> Foo for &'a [u8] {}
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-
fn a(v: &[u8]) -> Box<Foo + 'static> {
let x: Box<Foo + 'static> = Box::new(v);
//~^ ERROR cannot infer an appropriate lifetime due to conflicting
#![feature(box_syntax)]
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-
trait X {}
trait Iter {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-
trait X { fn foo(&self) {} }
fn p1<T>(v: T) -> Box<X+'static>
fn supply_F() {
want_F(foo);
- want_F(bar);
+
+ // FIXME(#33684) -- this should be a subtype, but current alg. rejects it incorrectly
+ want_F(bar); //~ ERROR E0308
+
want_F(baz);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-
fn ignore<T>(t: T) {}
fn nested<'x>(x: &'x isize) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-
fn borrowed_proc<'a>(x: &'a isize) -> Box<FnMut()->(isize) + 'a> {
// This is legal, because the region bound on `proc`
// states that it captures `x`.
fn main() {
let mut cl_box = {
let mut i = 3;
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
box_it(Box::new(|| i += 1)) //~ ERROR `i` does not live long enough
};
cl_box.cl.call_mut(());
}
fn main() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let s: Box<Trait<isize>> = Box::new(Struct { person: "Fred" });
//~^ ERROR `Struct: Trait<isize>` is not satisfied
s.f(1);
fn main() {
let person = "Fred".to_string();
let person: &str = &person; //~ ERROR `person` does not live long enough
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let s: Box<Trait<&'static str>> = Box::new(Struct { person: person });
}
fn a() {
test(22, std::default::Default::default());
- //~^ ERROR unable to infer enough type information about `U` [E0282]
+ //~^ ERROR type annotations needed [E0282]
//~| NOTE cannot infer type for `U`
- //~| NOTE type annotations or generic parameter binding
}
fn main() {}
fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-
fn main() {
// By-ref cases
{
// Issue #5062
fn main() {
- None; //~ ERROR unable to infer enough type information about `T` [E0282]
+ None; //~ ERROR type annotations needed [E0282]
//~| NOTE cannot infer type for `T`
- //~| NOTE type annotations or generic parameter binding
}
}
fn main() {
- S { o: &None }; //~ ERROR unable to infer enough type information about `T` [E0282]
+ S { o: &None }; //~ ERROR type annotations needed [E0282]
//~| NOTE cannot infer type for `T`
- //~| NOTE type annotations or generic parameter binding
}
_priv: !,
}
+fn foo() -> Option<NotSoSecretlyEmpty> {
+ None
+}
+
fn main() {
let x: &[!] = &[];
Err(Err(_y)) => (),
Err(Ok(_y)) => (), //~ ERROR unreachable pattern
}
+
+ while let Some(_y) = foo() {
+ //~^ ERROR unreachable pattern
+ }
}
}
fn main() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let i = Box::new(r { b: true });
let _j = i.clone(); //~ ERROR no method named `clone` found
println!("{:?}", i);
fn main() {
let _foo = Vec::new();
- //~^ ERROR unable to infer enough type information about `T` [E0282]
+ //~^ ERROR type annotations needed [E0282]
//~| NOTE cannot infer type for `T`
- //~| NOTE type annotations or generic parameter binding
+ //~| NOTE consider giving `_foo` a type
}
// ignore-tidy-linelength
// min-lldb-version: 310
-// ignore-gdb-version: 7.11.90 - 7.12
+// ignore-gdb-version: 7.11.90 - 7.12.9
// compile-flags:-g
// ignore-tidy-linelength
// min-lldb-version: 310
-// ignore-gdb-version: 7.11.90 - 7.12
+// ignore-gdb-version: 7.11.90 - 7.12.9
// compile-flags:-g
// ignore-tidy-linelength
// min-lldb-version: 310
-// ignore-gdb-version: 7.11.90 - 7.12
+// ignore-gdb-version: 7.11.90 - 7.12.9
// compile-flags:-g
// ignore-tidy-linelength
// min-lldb-version: 310
-// ignore-gdb-version: 7.11.90 - 7.12
+// ignore-gdb-version: 7.11.90 - 7.12.9
// compile-flags:-g
// ignore-tidy-linelength
// ignore-lldb
-// ignore-gdb-version: 7.11.90 - 7.12
+// ignore-gdb-version: 7.11.90 - 7.12.9
// compile-flags:-g
// ignore-tidy-linelength
// min-lldb-version: 310
-// ignore-gdb-version: 7.11.90 - 7.12
+// ignore-gdb-version: 7.11.90 - 7.12.9
// compile-flags:-g
// ignore-tidy-linelength
// min-lldb-version: 310
-// ignore-gdb-version: 7.11.90 - 7.12
+// ignore-gdb-version: 7.11.90 - 7.12.9
// compile-flags:-g
// ignore-tidy-linelength
// min-lldb-version: 310
-// ignore-gdb-version: 7.11.90 - 7.12
+// ignore-gdb-version: 7.11.90 - 7.12.9
// compile-flags:-g
// except according to those terms.
// min-lldb-version: 310
-// ignore-gdb-version: 7.11.90 - 7.12
+// ignore-gdb-version: 7.11.90 - 7.12.9
// compile-flags:-g
// ignore-tidy-linelength
// min-lldb-version: 310
-// ignore-gdb-version: 7.11.90 - 7.12
+// ignore-gdb-version: 7.11.90 - 7.12.9
// compile-flags:-g
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
impl Foo {
- #[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
- #[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn method_name2() { }
}
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
impl Foo {
- #[rustc_dirty(label="Hir", cfg="cfail2")]
+ #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
- #[rustc_metadata_dirty(cfg="cfail2")]
+ #[rustc_dirty(label="HirBody", cfg="cfail2")]
+ #[rustc_clean(label="HirBody", cfg="cfail3")]
+ #[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn method_body() {
println!("Hello, world!");
}
}
-// Change Method Privacy -----------------------------------------------------------
+
+// Change Method Body (inlined) ------------------------------------------------
+//
+// This should affect the method itself, but not the impl.
+#[cfg(cfail1)]
+impl Foo {
+ #[inline]
+ pub fn method_body_inlined() { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl Foo {
+ #[rustc_clean(label="Hir", cfg="cfail2")]
+ #[rustc_clean(label="Hir", cfg="cfail3")]
+ #[rustc_dirty(label="HirBody", cfg="cfail2")]
+ #[rustc_clean(label="HirBody", cfg="cfail3")]
+ #[rustc_metadata_dirty(cfg="cfail2")]
+ #[rustc_metadata_clean(cfg="cfail3")]
+ #[inline]
+ pub fn method_body_inlined() {
+ println!("Hello, world!");
+ }
+}
+
+
+// Change Method Privacy -------------------------------------------------------
#[cfg(cfail1)]
impl Foo {
pub fn method_privacy() { }
impl Foo {
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
- #[rustc_metadata_clean(cfg="cfail2")]
+ #[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn add_method_to_impl1(&self) { }
- #[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
- #[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn add_method_to_impl2(&self) { }
}
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
impl Foo {
- #[rustc_dirty(label="Hir", cfg="cfail2")]
+ #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
- #[rustc_metadata_dirty(cfg="cfail2")]
+ #[rustc_dirty(label="HirBody", cfg="cfail2")]
+ #[rustc_clean(label="HirBody", cfg="cfail3")]
+ // At the moment we explicitly ignore argument names in metadata, since they
+ // are not used in downstream crates (except in rustdoc)
+ #[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_method_parameter_name(&self, b: i64) { }
}
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
impl Foo {
- #[rustc_dirty(label="Hir", cfg="cfail2")]
+ #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
- #[rustc_metadata_dirty(cfg="cfail2")]
+ #[rustc_dirty(label="HirBody", cfg="cfail2")]
+ #[rustc_clean(label="HirBody", cfg="cfail3")]
+ // At the moment we explicitly ignore argument names in metadata, since they
+ // are not used in downstream crates (except in rustdoc)
+ #[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_method_parameter_order(&self, b: i64, a: i64) { }
}
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
impl<T> Bar<T> {
- #[rustc_dirty(label="Hir", cfg="cfail2")]
+ #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
impl Bar<u64> {
- #[rustc_dirty(label="Hir", cfg="cfail2")]
+ #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
impl<T: 'static> Bar<T> {
- #[rustc_dirty(label="Hir", cfg="cfail2")]
+ #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
impl<T: Clone> Bar<T> {
- #[rustc_dirty(label="Hir", cfg="cfail2")]
+ #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
trait TraitChangeModeSelfOwnToMut: Sized {
- #[rustc_dirty(label="Hir", cfg="cfail2")]
+ #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
+ #[rustc_dirty(label="HirBody", cfg="cfail2")]
+ #[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
fn method(mut self) {}
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub trait ChangeMethodNameTrait {
- #[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
- #[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
fn method_name2();
}
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
impl ChangeMethodNameTrait for Foo {
- #[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
- #[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
fn method_name2() { }
}
// Change Method Body -----------------------------------------------------------
//
-// This should affect the method itself, but not the trait.
+// This should affect the method itself, but not the impl.
pub trait ChangeMethodBodyTrait {
fn method_name();
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
impl ChangeMethodBodyTrait for Foo {
- #[rustc_dirty(label="Hir", cfg="cfail2")]
+ #[rustc_clean(label="Hir", cfg="cfail2")]
+ #[rustc_clean(label="Hir", cfg="cfail3")]
+ #[rustc_dirty(label="HirBody", cfg="cfail2")]
+ #[rustc_clean(label="HirBody", cfg="cfail3")]
+ #[rustc_metadata_clean(cfg="cfail2")]
+ #[rustc_metadata_clean(cfg="cfail3")]
+ fn method_name() {
+ ()
+ }
+}
+
+// Change Method Body (inlined fn) ---------------------------------------------
+//
+// This should affect the method itself, but not the impl.
+
+pub trait ChangeMethodBodyTraitInlined {
+ fn method_name();
+}
+
+#[cfg(cfail1)]
+impl ChangeMethodBodyTraitInlined for Foo {
+ #[inline]
+ fn method_name() { }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_clean(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+impl ChangeMethodBodyTraitInlined for Foo {
+ #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
+ #[rustc_dirty(label="HirBody", cfg="cfail2")]
+ #[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
+ #[inline]
fn method_name() {
()
}
}
-// Change Method Selfness -----------------------------------------------------------
+// Change Method Selfness ------------------------------------------------------
#[cfg(cfail1)]
pub trait ChangeMethodSelfnessTrait {
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
impl ChangeSelfTypeOfImpl for u64 {
- #[rustc_dirty(label="Hir", cfg="cfail2")]
+ #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
impl<T: 'static> AddLifetimeBoundToImplParameter for T {
- #[rustc_dirty(label="Hir", cfg="cfail2")]
+ #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
impl<T: Clone> AddTraitBoundToImplParameter for T {
- #[rustc_dirty(label="Hir", cfg="cfail2")]
+ #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// revisions: rpass1 cfail2
+// compile-flags: -Z query-dep-graph
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+// Sanity check for the dirty-clean system. We add #[rustc_dirty]/#[rustc_clean]
+// attributes in places that are not checked and make sure that this causes an
+// error.
+
+fn main() {
+
+ #[rustc_dirty(label="Hir", cfg="cfail2")]
+ //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute
+ {
+ // empty block
+ }
+
+ #[rustc_clean(label="Hir", cfg="cfail2")]
+ //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute
+ {
+ // empty block
+ }
+}
+
+struct _Struct {
+ #[rustc_dirty(label="Hir", cfg="cfail2")]
+ //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute
+ _field1: i32,
+
+ #[rustc_clean(label="Hir", cfg="cfail2")]
+ //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute
+ _field2: i32,
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// revisions: rpass1 cfail2
+// compile-flags: -Z query-dep-graph
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+// Sanity check for the dirty-clean system. We add
+// #[rustc_metadata_dirty]/#[rustc_metadata_clean] attributes in places that
+// are not checked and make sure that this causes an error.
+
+fn main() {
+
+ #[rustc_metadata_dirty(cfg="cfail2")]
+ //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute
+ {
+ // empty block
+ }
+
+ #[rustc_metadata_clean(cfg="cfail2")]
+ //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute
+ {
+ // empty block
+ }
+}
+
+struct _Struct {
+ #[rustc_metadata_dirty(cfg="cfail2")]
+ //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute
+ _field1: i32,
+
+ #[rustc_metadata_clean(cfg="cfail2")]
+ //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute
+ _field2: i32,
+}
+
--- /dev/null
+error[E0369]: binary operation `+` cannot be applied to type `&'static str`
+ --> src/test/ui/span/issue-39018.rs:2:13
+ |
+2 | let x = "Hello " + "World!";
+ | ^^^^^^^^
+ |
+note: `+` can't be used to concatenate two `&str` strings
+ --> src/test/ui/span/issue-39018.rs:2:13
+ |
+2 | let x = "Hello " + "World!";
+ | ^^^^^^^^
+help: to_owned() can be used to create an owned `String` from a string reference. This allows concatenation since the `String` is owned.
+ | let x = "Hello ".to_owned() + "World!";
+
+error[E0369]: binary operation `+` cannot be applied to type `World`
+ --> src/test/ui/span/issue-39018.rs:7:13
+ |
+7 | let y = World::Hello + World::Goodbye;
+ | ^^^^^^^^^^^^
+ |
+note: an implementation of `std::ops::Add` might be missing for `World`
+ --> src/test/ui/span/issue-39018.rs:7:13
+ |
+7 | let y = World::Hello + World::Goodbye;
+ | ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
fn main () {
(1, (2, 3)).1.1; //~ ERROR unexpected token
- //~^ HELP try parenthesizing the first index; e.g., `(foo.1).1`
+ //~^ HELP try parenthesizing the first index
+ //~| SUGGESTION ((1, (2, 3)).1).1
}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:derive-foo.rs
+// ignore-stage1
+// pp-exact
+// Testing that both the inner item and next outer item are
+// preserved, and that the first outer item parsed in main is not
+// accidentally carried over to each inner function
+
+#[macro_use]
+extern crate derive_foo;
+
+#[derive(Foo)]
+struct X;
+
+#[derive(Foo)]
+#[Bar]
+struct Y;
+
+#[derive(Foo)]
+struct WithRef {
+ x: X,
+ #[Bar]
+ y: Y,
+}
+
+#[derive(Foo)]
+enum Enum {
+
+ #[Bar]
+ Asdf,
+ Qwerty,
+}
+
+fn main() { }
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// pp-exact
-// Testing that both the inner item and next outer item are
-// preserved, and that the first outer item parsed in main is not
-// accidentally carried over to each inner function
-
-#![feature(custom_attribute)]
-#![feature(custom_derive)]
-
-#[derive(Serialize, Deserialize)]
-struct X;
-
-#[derive(Serialize, Deserialize)]
-struct WithRef<'a, T: 'a> {
- #[serde(skip_deserializing)]
- t: Option<&'a T>,
- #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
- x: X,
-}
-
-#[derive(Serialize, Deserialize)]
-enum EnumWith<T> {
- Unit,
- Newtype(
- #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
- X),
- Tuple(T,
- #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
- X),
- Struct {
- t: T,
- #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
- x: X,
- },
-}
-
-#[derive(Serialize, Deserialize)]
-struct Tuple<T>(T,
- #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
- X);
-
-fn main() { }
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Foo, attributes(Bar))]
+pub fn derive(input: TokenStream) -> TokenStream {
+ "".parse().unwrap()
+}
$(RUSTC) --cfg 'feature="bar"' --crate-type lib foo.rs
$(HOST_RPATH_ENV) '$(RUSTDOC)' --test --cfg 'feature="bar"' \
-L $(TMPDIR) foo.rs |\
- grep -q 'test foo_0 ... ok'
+ grep -q 'foo.rs - line 11 ... ok'
--- /dev/null
+-include ../tools.mk
+
+# aaa is a native static library
+# bbb is a rlib
+# ccc is a dylib
+# ddd is an executable
+
+all: $(call NATIVE_STATICLIB,aaa)
+ $(RUSTC) bbb.rs --crate-type=rlib
+
+ # Check that bbb does NOT contain the definition of `native_func`
+ nm $(TMPDIR)/libbbb.rlib | (! grep "T _*native_func")
+ nm $(TMPDIR)/libbbb.rlib | grep "U _*native_func"
+
+ # Check that aaa gets linked (either as `-l aaa` or `aaa.lib`) when building ccc.
+ $(RUSTC) ccc.rs -C prefer-dynamic --crate-type=dylib -Z print-link-args | grep -e "-l[\" ]*aaa" -e "aaa.lib"
+
+ # Check that aaa does NOT get linked when building ddd.
+ $(RUSTC) ddd.rs -Z print-link-args | (! grep -e "-l[\" ]*aaa" -e "aaa.lib")
+
+ $(call RUN,ddd)
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+void native_func() {}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "rlib"]
+#![feature(static_nobundle)]
+
+#[link(name = "aaa", kind = "static-nobundle")]
+extern {
+ pub fn native_func();
+}
+
+pub fn wrapped_func() {
+ unsafe {
+ native_func();
+ }
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "dylib"]
+
+extern crate bbb;
+
+pub fn do_work() {
+ unsafe { bbb::native_func(); }
+ bbb::wrapped_func();
+}
+
+pub fn do_work_generic<T>() {
+ unsafe { bbb::native_func(); }
+ bbb::wrapped_func();
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate ccc;
+
+fn main() {
+ ccc::do_work();
+ ccc::do_work_generic::<i16>();
+ ccc::do_work_generic::<i32>();
+}
reg.register_macro("identity", expand_identity);
reg.register_syntax_extension(
Symbol::intern("into_multi_foo"),
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
MultiModifier(Box::new(expand_into_foo_multi)));
reg.register_syntax_extension(
Symbol::intern("duplicate"),
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
MultiDecorator(Box::new(expand_duplicate)));
reg.register_syntax_extension(
Symbol::intern("caller"),
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
MultiDecorator(Box::new(expand_caller)));
}
pub fn plugin_registrar(reg: &mut Registry) {
let args = reg.args().to_owned();
reg.register_syntax_extension(Symbol::intern("plugin_args"),
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
NormalTT(Box::new(Expander { args: args, }), None, false));
}
}
fn main() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let obj = A { foo: Box::new([true, false]) };
let s = json::encode(&obj).unwrap();
let obj2: A = json::decode(&s).unwrap();
pub fn main() {
{
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let _x: Box<Fat<Trait>> = Box::<Fat<Foo>>::new(Fat { f: Foo });
}
unsafe {
pub fn main() {
{
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let _x: Box<Fat<[Foo]>> = Box::<Fat<[Foo; 3]>>::new(Fat { f: [Foo, Foo, Foo] });
}
unsafe {
fn main() {
let v = vec![1, 2, 3, 4, 5, 6];
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let r = pairwise_sub(Box::new(v.into_iter()));
assert_eq!(r, 9);
}
// rvalue expressions to be unsized. See #20169 for more information.
pub fn main() {
- // FIXME #22405: We cannot infer the type `Box<[isize; k]>` for
- // the r-value expression from the context `Box<[isize]>`, and
- // therefore the `box EXPR` desugaring breaks down.
- //
- // One could reasonably claim that the `box EXPR` desugaring is
- // effectively regressing half of Issue #20169. Hopefully we will
- // eventually fix that, at which point the `Box::new` calls below
- // should be replaced wth uses of `box`.
-
let _: Box<[isize]> = Box::new({ [1, 2, 3] });
let _: Box<[isize]> = Box::new(if true { [1, 2, 3] } else { [1, 3, 4] });
let _: Box<[isize]> = Box::new(match true { true => [1, 2, 3], false => [1, 3, 4] });
pub fn main() {
let a: A = Default::default();
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let b: Box<[_]> = Box::<[bool; 0]>::new([]);
assert_eq!(a.foo, b);
}
struct Foo(Box<[u8]>);
pub fn main() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let a = Foo(Box::new([0, 1, 2]));
let b = Foo(Box::new([0, 1, 2]));
assert_eq!(a, b);
}
fn main() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let mut a = Arr { ptr: Box::new([1, 2, 3]) };
foo(&mut a);
}
}
fn main() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let a = Arr { ptr: Box::new([1, 2, 3]) };
foo(&a);
}
let f2 : Box<Fat<[isize]>> = f1;
foo(&*f2);
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let f3 : Box<Fat<[isize]>> =
Box::<Fat<[_; 3]>>::new(Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] });
foo(&*f3);
// &*
//
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let f7: Box<ToBar> = Box::new(Bar1 {f :42});
bar(&*f7);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-
-
pub fn main() {
assert!(Some(Box::new(())).is_some());
}
fn parent() {
- let file = File::open(file!()).unwrap();
+ let file = File::open(env::current_exe().unwrap()).unwrap();
let tcp1 = TcpListener::bind("127.0.0.1:0").unwrap();
let tcp2 = tcp1.try_clone().unwrap();
let addr = tcp1.local_addr().unwrap();
}
let ctrl_clone = ctrl.clone();
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
::map(input, Box::new(|a,b| emit(&mut intermediates, ctrl.clone(), a, b)));
ctrl_clone.send(ctrl_proto::mapper_done).unwrap();
}
// cause a compilation error. Issue #18772.
fn adder(y: isize) -> Box<Fn(isize) -> isize + 'static> {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
Box::new(move |x| y + x)
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-stage0
-// ignore-stage1
-
// MSVC doesn't support 128 bit integers, and other Windows
// C compilers have very inconsistent views on how the ABI
// should look like.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-stage0
-// ignore-stage1
-
// ignore-emscripten
#![feature(i128_type, test)]
#![allow(dead_code)]
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-
trait Foo { fn dummy(&self) { } }
impl Foo for isize {}
fn foo(_: [&Foo; 2]) {}
}
fn main() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
S {f: Box::new(F), g: Box::new(F) };
}
// except according to those terms.
fn main() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
fn test() -> Box<std::any::Any + 'static> { Box::new(1) }
println!("{:?}", test())
}
impl<'a> Foo<'a> {
fn new<F>(listener: F) -> Foo<'a> where F: FnMut() + 'a {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
Foo { listener: Box::new(listener) }
}
}
// All 3 expressions should work in that the argument gets
// coerced to a trait object
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-
// pretty-expanded FIXME #23616
fn main() {
impl<'a, 'b, F> IntoMatcher<'a, CharPredMatcher<'a, 'b>> for F where F: FnMut(char) -> bool + 'b {
fn into_matcher(self, s: &'a str) -> CharPredMatcher<'a, 'b> {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
CharPredMatcher {
str: s,
pred: Box::new(self),
impl<'a, I: 'a, O: 'a> Parser<'a, I, O> {
fn compose<K: 'a>(mut self, mut rhs: Parser<'a, O, K>) -> Parser<'a, I, K> {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
Parser {
parse: Box::new(move |x: I| {
match (self.parse)(x) {
fn main() {
// There is currently no safe way to construct a `Box<str>`, so improvise
- //
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let box_arr: Box<[u8]> = Box::new(['h' as u8, 'e' as u8, 'l' as u8, 'l' as u8, 'o' as u8]);
let box_str: Box<str> = unsafe { std::mem::transmute(box_arr) };
assert_eq!(&*box_str, "hello");
// pretty-expanded FIXME #23616
fn main() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let functions: [Box<Fn() -> Option<()>>; 1] = [Box::new(|| None)];
let _: Option<Vec<()>> = functions.iter().map(|f| (*f)()).collect();
type Connection = Box<FnMut(Vec<u8>) + 'static>;
fn f() -> Option<Connection> {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let mock_connection: Connection = Box::new(|_| {});
Some(mock_connection)
}
thread::spawn(move|| {
let mut samples_chan = samples_chan;
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let callback: SamplesFn = Box::new(move |buffer| {
for i in 0..buffer.len() {
println!("{}: {}", i, buffer[i])
// except according to those terms.
#![feature(i128_type)]
-// SNAP: run on all stages after snapshot, i128 currently doesn't work on stages 0 and 1
-// ignore-stage1
-// ignore-stage0
-
fn main() {
let _ = -0x8000_0000_0000_0000_0000_0000_0000_0000i128;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// compile-flags: -g
#[derive(PartialEq, Eq)]
struct NewBool(bool);
// Test that the lambda kind is inferred correctly as a return
// expression
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
// pretty-expanded FIXME #23616
fn unique() -> Box<FnMut()+'static> { return Box::new(|| ()); }
// Test that the lambda kind is inferred correctly as a return
// expression
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
// pretty-expanded FIXME #23616
fn unique() -> Box<FnMut()+'static> { Box::new(|| ()) }
// Parser test for #37765
-fn with_parens<T: ToString>(arg: T) -> String { //~WARN dead_code
- return (<T as ToString>::to_string(&arg)); //~WARN unused_parens
+fn with_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `with_parens`
+ return (<T as ToString>::to_string(&arg)); //~WARN unnecessary parentheses around `return` value
}
-fn no_parens<T: ToString>(arg: T) -> String { //~WARN dead_code
+fn no_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `no_parens`
return <T as ToString>::to_string(&arg);
}
#![allow(unused_variables)]
#![allow(unknown_features)]
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-
// Should pass region checking.
fn ok(f: Box<FnMut(&usize)>) {
// Here, g is a function that can accept a usize pointer with
impl<'a,'tcx> Foo<'a,'tcx> {
fn bother(&mut self) -> isize {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
self.elaborate_bounds(Box::new(|this| {
// (*) Here: type of `this` is `&'f0 Foo<&'f1, '_2>`,
// where `'f0` and `'f1` are fresh, free regions that
struct Foo(Box<[u8]>);
pub fn main() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
println!("{:?}", Foo(Box::new([0, 1, 2])));
}
}
fn check_names(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
for pet in arc.iter() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
pet.name(Box::new(|name| {
assert!(name.as_bytes()[0] == 'a' as u8 && name.as_bytes()[1] == 'l' as u8);
}))
pub fn main() {
let a = Struct { x: 1, y: 2 };
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let b: Box<Trait<&'static str>> = Box::new(a);
b.f("Mary");
let c: &Trait<&'static str> = &a;
fn foo(mut a: Box<Write>) {}
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-
pub fn main() {
let a = Struct { x: 1, y: 2 };
let b: Box<Trait> = Box::new(a);
use std::ops::FnMut;
fn make_adder(x: isize) -> Box<FnMut(isize)->isize + 'static> {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
Box::new(move |y| { x + y })
}
use std::ops::FnMut;
fn make_adder(x: isize) -> Box<FnMut(isize)->isize + 'static> {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
Box::new(move |y| { x + y })
}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:--test
+
+// This file tests the source-partitioning behavior of rustdoc.
+// Each test contains some code that should be put into the generated
+// `fn main` and some attributes should be left outside (except the first
+// one, which has no attributes).
+// If the #![recursion_limit] attribute is incorrectly left inside,
+// then the tests will fail because the macro recurses 128 times.
+
+/// ```
+/// assert_eq!(1 + 1, 2);
+/// ```
+pub fn simple() {}
+
+/// ```
+/// #![recursion_limit = "1024"]
+/// macro_rules! recurse {
+/// (()) => {};
+/// (() $($rest:tt)*) => { recurse!($($rest)*); }
+/// }
+/// recurse!(() () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ());
+/// assert_eq!(1 + 1, 2);
+/// ```
+pub fn non_feature_attr() {}
+
+/// ```
+/// #![feature(core_intrinsics)]
+/// assert_eq!(1 + 1, 2);
+/// ```
+pub fn feature_attr() {}
+
+/// ```
+/// #![feature(core_intrinsics)]
+/// #![recursion_limit = "1024"]
+/// macro_rules! recurse {
+/// (()) => {};
+/// (() $($rest:tt)*) => { recurse!($($rest)*); }
+/// }
+/// recurse!(() () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ());
+/// assert_eq!(1 + 1, 2);
+/// ```
+pub fn both_attrs() {}
+
+/// ```
+/// #![recursion_limit = "1024"]
+/// #![feature(core_intrinsics)]
+/// macro_rules! recurse {
+/// (()) => {};
+/// (() $($rest:tt)*) => { recurse!($($rest)*); }
+/// }
+/// recurse!(() () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ()
+/// () () () () () () () ());
+/// assert_eq!(1 + 1, 2);
+/// ```
+pub fn both_attrs_reverse() {}
+
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --test
+// check-test-line-numbers-match
+
+/// This is a Foo;
+///
+/// ```
+/// println!("baaaaaar");
+/// ```
+pub struct Foo;
+
+/// This is a Bar;
+///
+/// ```
+/// println!("fooooo");
+/// ```
+pub struct Bar;
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let (x,) = (vec![],);
+}
--- /dev/null
+error[E0282]: type annotations needed
+ --> $DIR/issue-38812-2.rs:12:17
+ |
+12 | let (x,) = (vec![],);
+ | ---- ^^^^^^ cannot infer type for `T`
+ | |
+ | consider giving a type to pattern
+ |
+ = note: this error originates in a macro outside of the current crate
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let x = vec![];
+}
--- /dev/null
+error[E0282]: type annotations needed
+ --> $DIR/issue-38812.rs:12:13
+ |
+12 | let x = vec![];
+ | - ^^^^^^ cannot infer type for `T`
+ | |
+ | consider giving `x` a type
+ |
+ = note: this error originates in a macro outside of the current crate
+
+error: aborting due to previous error
+
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- let x = vec![];
-}
+++ /dev/null
-error[E0282]: unable to infer enough type information about `T`
- --> $DIR/repair_span_std_macros.rs:12:13
- |
-12 | let x = vec![];
- | ^^^^^^ cannot infer type for `T`
- |
- = note: type annotations or generic parameter binding required
- = note: this error originates in a macro outside of the current crate
-
-error: aborting due to previous error
-
-error[E0276]: impl has stricter requirements than trait, #[deny(extra_requirement_in_impl)] on by default
+error[E0276]: impl has stricter requirements than trait
--> $DIR/proj-outlives-region.rs:22:5
|
17 | fn foo() where T: 'a;
22 | fn foo() where U: 'a { } //~ ERROR E0276
| ^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `U: 'a`
|
+ = note: #[deny(extra_requirement_in_impl)] on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #37166 <https://github.com/rust-lang/rust/issues/37166>
-error[E0276]: impl has stricter requirements than trait, #[deny(extra_requirement_in_impl)] on by default
+error[E0276]: impl has stricter requirements than trait
--> $DIR/region-unrelated.rs:22:5
|
17 | fn foo() where T: 'a;
22 | fn foo() where V: 'a { }
| ^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `V: 'a`
|
+ = note: #[deny(extra_requirement_in_impl)] on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #37166 <https://github.com/rust-lang/rust/issues/37166>
-error: custom derive attribute panicked
+error: proc-macro derive panicked
--> $DIR/issue-36935.rs:17:15
|
17 | #[derive(Foo, Bar)]
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use Foo;
+
+use Foo1;
+
+fn main() {}
--- /dev/null
+error[E0432]: unresolved import `Foo`
+ --> $DIR/issue-38054-do-not-show-unresolved-names.rs:11:5
+ |
+11 | use Foo;
+ | ^^^ no `Foo` in the root
+
+error[E0432]: unresolved import `Foo1`
+ --> $DIR/issue-38054-do-not-show-unresolved-names.rs:13:5
+ |
+13 | use Foo1;
+ | ^^^^ no `Foo1` in the root
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -A bad-style
+
+fn main() {
+ let _InappropriateCamelCasing = true;
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -D bad-style
+
+fn main() {
+ let _InappropriateCamelCasing = true;
+}
--- /dev/null
+error: variable `_InappropriateCamelCasing` should have a snake case name such as `_inappropriate_camel_casing`
+ --> $DIR/command-line-lint-group-deny.rs:14:9
+ |
+14 | let _InappropriateCamelCasing = true;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `-D non-snake-case` implied by `-D bad-style`
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -F bad-style
+
+fn main() {
+ let _InappropriateCamelCasing = true;
+}
--- /dev/null
+error: variable `_InappropriateCamelCasing` should have a snake case name such as `_inappropriate_camel_casing`
+ --> $DIR/command-line-lint-group-forbid.rs:14:9
+ |
+14 | let _InappropriateCamelCasing = true;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `-F non-snake-case` implied by `-F bad-style`
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -W bad-style
+
+fn main() {
+ let _InappropriateCamelCasing = true;
+}
--- /dev/null
+warning: variable `_InappropriateCamelCasing` should have a snake case name such as `_inappropriate_camel_casing`
+ --> $DIR/command-line-lint-group-warn.rs:14:9
+ |
+14 | let _InappropriateCamelCasing = true;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `-W non-snake-case` implied by `-W bad-style`
+
--- /dev/null
+// Copyright 2014–2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(bad_style)]
+#![allow(dead_code)]
+
+fn CamelCase() {}
+
+#[allow(bad_style)]
+mod test {
+ fn CamelCase() {}
+
+ #[forbid(bad_style)]
+ mod bad {
+ fn CamelCase() {}
+
+ static bad: isize = 1;
+ }
+
+ mod warn {
+ #![warn(bad_style)]
+
+ fn CamelCase() {}
+
+ struct snake_case;
+ }
+}
+
+fn main() {}
--- /dev/null
+error: function `CamelCase` should have a snake case name such as `camel_case`
+ --> $DIR/lint-group-style.rs:14:1
+ |
+14 | fn CamelCase() {}
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: #[deny(non_snake_case)] implied by #[deny(bad_style)]
+note: lint level defined here
+ --> $DIR/lint-group-style.rs:11:9
+ |
+11 | #![deny(bad_style)]
+ | ^^^^^^^^^
+
+error: function `CamelCase` should have a snake case name such as `camel_case`
+ --> $DIR/lint-group-style.rs:22:9
+ |
+22 | fn CamelCase() {}
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: #[forbid(non_snake_case)] implied by #[forbid(bad_style)]
+note: lint level defined here
+ --> $DIR/lint-group-style.rs:20:14
+ |
+20 | #[forbid(bad_style)]
+ | ^^^^^^^^^
+
+error: static variable `bad` should have an upper case name such as `BAD`
+ --> $DIR/lint-group-style.rs:24:9
+ |
+24 | static bad: isize = 1;
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: #[forbid(non_upper_case_globals)] implied by #[forbid(bad_style)]
+note: lint level defined here
+ --> $DIR/lint-group-style.rs:20:14
+ |
+20 | #[forbid(bad_style)]
+ | ^^^^^^^^^
+
+warning: function `CamelCase` should have a snake case name such as `camel_case`
+ --> $DIR/lint-group-style.rs:30:9
+ |
+30 | fn CamelCase() {}
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: #[warn(non_snake_case)] implied by #[warn(bad_style)]
+note: lint level defined here
+ --> $DIR/lint-group-style.rs:28:17
+ |
+28 | #![warn(bad_style)]
+ | ^^^^^^^^^
+
+warning: type `snake_case` should have a camel case name such as `SnakeCase`
+ --> $DIR/lint-group-style.rs:32:9
+ |
+32 | struct snake_case;
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)]
+note: lint level defined here
+ --> $DIR/lint-group-style.rs:28:17
+ |
+28 | #![warn(bad_style)]
+ | ^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
-error[E0282]: unable to infer enough type information about `X`
+error[E0282]: type annotations needed
--> $DIR/missing-type-parameter.rs:14:5
|
14 | foo();
| ^^^ cannot infer type for `X`
- |
- = note: type annotations or generic parameter binding required
error: aborting due to previous error
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// In this fn, the type `F` is a function that takes a reference to a
+// struct and returns another reference with the same lifetime.
+//
+// Meanwhile, the bare fn `foo` takes a reference to a struct with
+// *ANY* lifetime and returns a reference with the 'static lifetime.
+// This can safely be considered to be an instance of `F` because all
+// lifetimes are sublifetimes of 'static.
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+struct S;
+
+// Given 'cx, return 'cx
+type F = for<'cx> fn(&'cx S) -> &'cx S;
+fn want_F(f: F) { }
+
+// Given anything, return 'static
+type G = for<'cx> fn(&'cx S) -> &'static S;
+fn want_G(f: G) { }
+
+// Should meet both.
+fn foo(x: &S) -> &'static S {
+ panic!()
+}
+
+// Should meet both.
+fn bar<'a,'b>(x: &'a S) -> &'b S {
+ panic!()
+}
+
+// Meets F, but not G.
+fn baz(x: &S) -> &S {
+ panic!()
+}
+
+fn supply_F() {
+ want_F(foo);
+
+ // FIXME(#33684) -- this should be a subtype, but current alg. rejects it incorrectly
+ want_F(bar); //~ ERROR E0308
+
+ want_F(baz);
+}
+
+pub fn main() {
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/regions-fn-subtyping-return-static.rs:51:12
+ |
+51 | want_F(bar); //~ ERROR E0308
+ | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx
+ |
+ = note: expected type `fn(&'cx S) -> &'cx S`
+ found type `fn(&'a S) -> &S {bar::<'_>}`
+ = note: lifetime parameter `'b` declared on fn `bar` appears only in the return type, but here is required to be higher-ranked, which means that `'b` must appear in both argument and return types
+ = note: this error is the result of a recent bug fix; for more information, see issue #33685 <https://github.com/rust-lang/rust/issues/33685>
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(pub_restricted)]
+
+pub mod m {
+ pub struct S(u8);
+
+ pub mod n {
+ pub(m) struct Z(pub(m::n) u8);
+ }
+}
+
+pub use m::S;
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:privacy-struct-ctor.rs
+
+#![feature(pub_restricted)]
+
+extern crate privacy_struct_ctor as xcrate;
+
+mod m {
+ pub struct S(u8);
+
+ pub mod n {
+ pub(m) struct Z(pub(m::n) u8);
+ }
+
+ use m::n::Z; // OK, only the type is imported
+
+ fn f() {
+ n::Z; //~ ERROR tuple struct `Z` is private
+ Z;
+ //~^ ERROR expected value, found struct `Z`
+ //~| NOTE tuple struct constructors with private fields are invisible outside of their mod
+ }
+}
+
+use m::S; // OK, only the type is imported
+
+fn main() {
+ m::S; //~ ERROR tuple struct `S` is private
+ S;
+ //~^ ERROR expected value, found struct `S`
+ //~| NOTE constructor is not visible here due to private fields
+ m::n::Z; //~ ERROR tuple struct `Z` is private
+
+ xcrate::m::S; //~ ERROR tuple struct `S` is private
+ xcrate::S;
+ //~^ ERROR expected value, found struct `xcrate::S`
+ //~| NOTE constructor is not visible here due to private fields
+ xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private
+}
--- /dev/null
+error[E0423]: expected value, found struct `Z`
+ --> $DIR/privacy-struct-ctor.rs:28:9
+ |
+28 | Z;
+ | ^
+ | |
+ | did you mean `Z { /* fields */ }`?
+ | constructor is not visible here due to private fields
+ |
+ = help: possible better candidate is found in another module, you can import it into scope:
+ `use m::n::Z;`
+
+error[E0423]: expected value, found struct `S`
+ --> $DIR/privacy-struct-ctor.rs:38:5
+ |
+38 | S;
+ | ^
+ | |
+ | did you mean `S { /* fields */ }`?
+ | constructor is not visible here due to private fields
+ |
+ = help: possible better candidate is found in another module, you can import it into scope:
+ `use m::S;`
+
+error[E0423]: expected value, found struct `xcrate::S`
+ --> $DIR/privacy-struct-ctor.rs:44:5
+ |
+44 | xcrate::S;
+ | ^^^^^^^^^
+ | |
+ | did you mean `xcrate::S { /* fields */ }`?
+ | constructor is not visible here due to private fields
+ |
+ = help: possible better candidate is found in another module, you can import it into scope:
+ `use m::S;`
+
+error: tuple struct `Z` is private
+ --> $DIR/privacy-struct-ctor.rs:27:9
+ |
+27 | n::Z; //~ ERROR tuple struct `Z` is private
+ | ^^^^
+
+error: tuple struct `S` is private
+ --> $DIR/privacy-struct-ctor.rs:37:5
+ |
+37 | m::S; //~ ERROR tuple struct `S` is private
+ | ^^^^
+
+error: tuple struct `Z` is private
+ --> $DIR/privacy-struct-ctor.rs:41:5
+ |
+41 | m::n::Z; //~ ERROR tuple struct `Z` is private
+ | ^^^^^^^
+
+error: tuple struct `S` is private
+ --> $DIR/privacy-struct-ctor.rs:43:5
+ |
+43 | xcrate::m::S; //~ ERROR tuple struct `S` is private
+ | ^^^^^^^^^^^^
+
+error: tuple struct `Z` is private
+ --> $DIR/privacy-struct-ctor.rs:47:5
+ |
+47 | xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors
+
f: Box<FnMut() + 'a>
}
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
fn call<F>(mut f: F) where F: FnMut(Fn) {
f(Box::new(|| {
//~^ ERROR: cannot borrow `f` as mutable more than once
fn test7() {
fn foo<F>(_: F) where F: FnMut(Box<FnMut(isize)>, isize) {}
let mut f = |g: Box<FnMut(isize)>, b: isize| {};
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
f(Box::new(|a| {
foo(f);
//~^ ERROR cannot move `f` into closure because it is borrowed
error[E0499]: cannot borrow `f` as mutable more than once at a time
- --> $DIR/borrowck-call-is-borrow-issue-12224.rs:23:16
+ --> $DIR/borrowck-call-is-borrow-issue-12224.rs:22:16
|
-23 | f(Box::new(|| {
+22 | f(Box::new(|| {
| - ^^ second mutable borrow occurs here
| |
| first mutable borrow occurs here
-24 | //~^ ERROR: cannot borrow `f` as mutable more than once
-25 | f((Box::new(|| {})))
+23 | //~^ ERROR: cannot borrow `f` as mutable more than once
+24 | f((Box::new(|| {})))
| - borrow occurs due to use of `f` in closure
-26 | }));
+25 | }));
| - first borrow ends here
error: cannot borrow immutable borrowed content `*f` as mutable
- --> $DIR/borrowck-call-is-borrow-issue-12224.rs:36:5
+ --> $DIR/borrowck-call-is-borrow-issue-12224.rs:35:5
|
-35 | fn test2<F>(f: &F) where F: FnMut() {
+34 | fn test2<F>(f: &F) where F: FnMut() {
| -- use `&mut F` here to make mutable
-36 | (*f)(); //~ ERROR: cannot borrow immutable borrowed content `*f` as mutable
+35 | (*f)(); //~ ERROR: cannot borrow immutable borrowed content `*f` as mutable
| ^^^^ cannot borrow as mutable
error: cannot borrow immutable `Box` content `*f.f` as mutable
- --> $DIR/borrowck-call-is-borrow-issue-12224.rs:44:5
+ --> $DIR/borrowck-call-is-borrow-issue-12224.rs:43:5
|
-43 | fn test4(f: &Test) {
+42 | fn test4(f: &Test) {
| ----- use `&mut Test` here to make mutable
-44 | f.f.call_mut(()) //~ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable
+43 | f.f.call_mut(()) //~ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable
| ^^^ cannot borrow as mutable
error[E0504]: cannot move `f` into closure because it is borrowed
- --> $DIR/borrowck-call-is-borrow-issue-12224.rs:63:13
+ --> $DIR/borrowck-call-is-borrow-issue-12224.rs:61:13
|
-62 | f(Box::new(|a| {
+60 | f(Box::new(|a| {
| - borrow of `f` occurs here
-63 | foo(f);
+61 | foo(f);
| ^ move into closure occurs here
error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
- --> $DIR/borrowck-call-is-borrow-issue-12224.rs:63:13
+ --> $DIR/borrowck-call-is-borrow-issue-12224.rs:61:13
|
-63 | foo(f);
+61 | foo(f);
| ^ cannot move out of captured outer variable in an `FnMut` closure
error: aborting due to 5 previous errors
19 | let theTwo = 2;
| ^^^^^^
|
+ = note: #[deny(non_snake_case)] implied by #[deny(warnings)]
note: lint level defined here
--> $DIR/issue-24690.rs:16:9
|
|
20 | let theOtherTwo = 2;
| ^^^^^^^^^^^
+ |
+ = note: #[deny(non_snake_case)] implied by #[deny(warnings)]
error: unused variable: `theOtherTwo`
--> $DIR/issue-24690.rs:20:9
20 | let theOtherTwo = 2;
| ^^^^^^^^^^^
|
+ = note: #[deny(unused_variables)] implied by #[deny(warnings)]
note: lint level defined here
--> $DIR/issue-24690.rs:16:9
|
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn main() {
+ let x = "Hello " + "World!";
+
+ // Make sure that the span outputs a warning
+ // for not having an implementation for std::ops::Add
+ // that won't output for the above string concatenation
+ let y = World::Hello + World::Goodbye;
+}
+
+enum World {
+ Hello,
+ Goodbye,
+}
--- /dev/null
+error[E0369]: binary operation `+` cannot be applied to type `&'static str`
+ --> $DIR/issue-39018.rs:12:13
+ |
+12 | let x = "Hello " + "World!";
+ | ^^^^^^^^
+ |
+note: `+` can't be used to concatenate two `&str` strings
+ --> $DIR/issue-39018.rs:12:13
+ |
+12 | let x = "Hello " + "World!";
+ | ^^^^^^^^
+help: to_owned() can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left.
+ | let x = "Hello ".to_owned() + "World!";
+
+error[E0369]: binary operation `+` cannot be applied to type `World`
+ --> $DIR/issue-39018.rs:17:13
+ |
+17 | let y = World::Hello + World::Goodbye;
+ | ^^^^^^^^^^^^
+ |
+note: an implementation of `std::ops::Add` might be missing for `World`
+ --> $DIR/issue-39018.rs:17:13
+ |
+17 | let y = World::Hello + World::Goodbye;
+ | ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
-warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd`, #[warn(unused_imports)] on by default
+warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd`
--> $DIR/multispan-import-lint.rs:11:16
|
11 | use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd};
| ^^ ^^^ ^^^^^^^^^ ^^^^^^^^^^
+ |
+ = note: #[warn(unused_imports)] on by default
Test {
name: "cargo",
repo: "https://github.com/rust-lang/cargo",
- sha: "2324c2bbaf7fc6ea9cbdd77c034ef1af769cb617",
+ sha: "0e1e34be7540bdaed4918457654fbf028cf69e56",
lock: None,
},
Test {
// Print one character per test instead of one line
pub quiet: bool,
+ // where to find the qemu test client process, if we're using it
+ pub qemu_test_client: Option<PathBuf>,
+
// Configuration for various run-make tests frobbing things like C compilers
// or querying about various LLVM component information.
pub cc: String,
pub incremental_dir: Option<PathBuf>,
// Specifies that a cfail test must actually compile without errors.
pub must_compile_successfully: bool,
+ // rustdoc will test the output of the `--test` option
+ pub check_test_line_numbers_match: bool,
}
impl TestProps {
forbid_output: vec![],
incremental_dir: None,
must_compile_successfully: false,
+ check_test_line_numbers_match: false,
}
}
if !self.must_compile_successfully {
self.must_compile_successfully = parse_must_compile_successfully(ln);
}
+
+ if !self.check_test_line_numbers_match {
+ self.check_test_line_numbers_match = parse_check_test_line_numbers_match(ln);
+ }
});
for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] {
parse_name_directive(line, "must-compile-successfully")
}
+fn parse_check_test_line_numbers_match(line: &str) -> bool {
+ parse_name_directive(line, "check-test-line-numbers-match")
+}
+
fn parse_env(line: &str, name: &str) -> Option<(String, String)> {
parse_name_value_directive(line, name).map(|nv| {
// nv is either FOO or FOO=BAR
reqopt("", "llvm-components", "list of LLVM components built in", "LIST"),
reqopt("", "llvm-cxxflags", "C++ flags for LLVM", "FLAGS"),
optopt("", "nodejs", "the name of nodejs", "PATH"),
+ optopt("", "qemu-test-client", "path to the qemu test client", "PATH"),
optflag("h", "help", "show this message")];
let (argv0, args_) = args.split_first().unwrap();
lldb_python_dir: matches.opt_str("lldb-python-dir"),
verbose: matches.opt_present("verbose"),
quiet: matches.opt_present("quiet"),
+ qemu_test_client: matches.opt_str("qemu-test-client").map(PathBuf::from),
cc: matches.opt_str("cc").unwrap(),
cxx: matches.opt_str("cxx").unwrap(),
// time.
env::set_var("RUST_TEST_THREADS", "1");
}
+
+ DebugInfoGdb => {
+ if config.qemu_test_client.is_some() {
+ println!("WARNING: debuginfo tests are not available when \
+ testing with QEMU");
+ return
+ }
+ }
_ => { /* proceed */ }
}
}
_ => {
- // android has it's own gdb handling
+ // android has its own gdb handling
if config.mode == DebugInfoGdb && config.gdb.is_none() {
panic!("gdb not available but debuginfo gdb debuginfo test requested");
}
"arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => {
self._arm_exec_compiled_test(env)
}
- _=> {
+
+ // This is pretty similar to below, we're transforming:
+ //
+ // program arg1 arg2
+ //
+ // into
+ //
+ // qemu-test-client run program:support-lib.so arg1 arg2
+ //
+ // The test-client program will upload `program` to the emulator
+ // along with all other support libraries listed (in this case
+ // `support-lib.so`. It will then execute the program on the
+ // emulator with the arguments specified (in the environment we give
+ // the process) and then report back the same result.
+ _ if self.config.qemu_test_client.is_some() => {
+ let aux_dir = self.aux_output_dir_name();
+ let mut args = self.make_run_args();
+ let mut program = args.prog.clone();
+ if let Ok(entries) = aux_dir.read_dir() {
+ for entry in entries {
+ let entry = entry.unwrap();
+ if !entry.path().is_file() {
+ continue
+ }
+ program.push_str(":");
+ program.push_str(entry.path().to_str().unwrap());
+ }
+ }
+ args.args.insert(0, program);
+ args.args.insert(0, "run".to_string());
+ args.prog = self.config.qemu_test_client.clone().unwrap()
+ .into_os_string().into_string().unwrap();
+ self.compose_and_run(args,
+ env,
+ self.config.run_lib_path.to_str().unwrap(),
+ Some(aux_dir.to_str().unwrap()),
+ None)
+ }
+ _ => {
let aux_dir = self.aux_output_dir_name();
self.compose_and_run(self.make_run_args(),
env,
if !proc_res.status.success() {
self.fatal_proc_rec("rustdoc failed!", &proc_res);
}
- let root = self.find_rust_src_root().unwrap();
- let res = self.cmd2procres(Command::new(&self.config.docck_python)
- .arg(root.join("src/etc/htmldocck.py"))
- .arg(out_dir)
- .arg(&self.testpaths.file));
- if !res.status.success() {
- self.fatal_proc_rec("htmldocck failed!", &res);
+ if self.props.check_test_line_numbers_match == true {
+ self.check_rustdoc_test_option(proc_res);
+ } else {
+ let root = self.find_rust_src_root().unwrap();
+ let res = self.cmd2procres(Command::new(&self.config.docck_python)
+ .arg(root.join("src/etc/htmldocck.py"))
+ .arg(out_dir)
+ .arg(&self.testpaths.file));
+ if !res.status.success() {
+ self.fatal_proc_rec("htmldocck failed!", &res);
+ }
+ }
+ }
+
+ fn check_rustdoc_test_option(&self, res: ProcRes) {
+ let mut file = fs::File::open(&self.testpaths.file)
+ .expect("markdown_test_output_check_entry File::open failed");
+ let mut content = String::new();
+ file.read_to_string(&mut content)
+ .expect("markdown_test_output_check_entry read_to_string failed");
+ let mut ignore = false;
+ let mut v: Vec<usize> =
+ content.lines()
+ .enumerate()
+ .filter_map(|(line_nb, line)| {
+ let sline = line.split("///").last().unwrap_or("");
+ let line = sline.trim_left();
+ if line.starts_with("```") {
+ if ignore {
+ ignore = false;
+ None
+ } else {
+ ignore = true;
+ Some(line_nb + 1)
+ }
+ } else {
+ None
+ }
+ })
+ .collect();
+
+ let mut tested = 0;
+ for _ in res.stdout.split("\n")
+ .filter(|s| s.starts_with("test "))
+ .inspect(|s| {
+ let tmp: Vec<&str> = s.split(" - line ").collect();
+ if tmp.len() == 2 {
+ tested += 1;
+ let line = tmp[1].split(" ...")
+ .next()
+ .unwrap_or("0")
+ .parse()
+ .unwrap_or(0);
+ if let Ok(pos) = v.binary_search(&line) {
+ v.remove(pos);
+ } else {
+ self.fatal_proc_rec(
+ &format!("Not found doc test: \"{}\" in {:?}", s, v),
+ &res);
+ }
+ }
+ }) {}
+ if tested == 0 {
+ self.fatal_proc_rec("No test has been found", &res);
+ } else if v.len() != 0 {
+ self.fatal_proc_rec(&format!("Not found test at line{} {:?}",
+ if v.len() > 1 { "s" } else { "" }, v),
+ &res);
}
}
--- /dev/null
+[package]
+name = "qemu-test-client"
+version = "0.1.0"
+authors = ["The Rust Project Developers"]
+
+[dependencies]
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// This is a small client program intended to pair with `qemu-test-server` in
+/// this repository. This client connects to the server over TCP and is used to
+/// push artifacts and run tests on the server instead of locally.
+///
+/// Here is also where we bake in the support to spawn the QEMU emulator as
+/// well.
+
+use std::env;
+use std::fs::File;
+use std::io::prelude::*;
+use std::io::{self, BufWriter};
+use std::net::TcpStream;
+use std::path::Path;
+use std::process::{Command, Stdio};
+use std::thread;
+use std::time::Duration;
+
+macro_rules! t {
+ ($e:expr) => (match $e {
+ Ok(e) => e,
+ Err(e) => panic!("{} failed with {}", stringify!($e), e),
+ })
+}
+
+fn main() {
+ let mut args = env::args().skip(1);
+
+ match &args.next().unwrap()[..] {
+ "spawn-emulator" => {
+ spawn_emulator(Path::new(&args.next().unwrap()),
+ Path::new(&args.next().unwrap()))
+ }
+ "push" => {
+ push(Path::new(&args.next().unwrap()))
+ }
+ "run" => {
+ run(args.next().unwrap(), args.collect())
+ }
+ cmd => panic!("unknown command: {}", cmd),
+ }
+}
+
+fn spawn_emulator(rootfs: &Path, tmpdir: &Path) {
+ // Generate a new rootfs image now that we've updated the test server
+ // executable. This is the equivalent of:
+ //
+ // find $rootfs -print 0 | cpio --null -o --format=newc > rootfs.img
+ let rootfs_img = tmpdir.join("rootfs.img");
+ let mut cmd = Command::new("cpio");
+ cmd.arg("--null")
+ .arg("-o")
+ .arg("--format=newc")
+ .stdin(Stdio::piped())
+ .stdout(Stdio::piped())
+ .current_dir(rootfs);
+ let mut child = t!(cmd.spawn());
+ let mut stdin = child.stdin.take().unwrap();
+ let rootfs = rootfs.to_path_buf();
+ thread::spawn(move || add_files(&mut stdin, &rootfs, &rootfs));
+ t!(io::copy(&mut child.stdout.take().unwrap(),
+ &mut t!(File::create(&rootfs_img))));
+ assert!(t!(child.wait()).success());
+
+ // Start up the emulator, in the background
+ let mut cmd = Command::new("qemu-system-arm");
+ cmd.arg("-M").arg("vexpress-a15")
+ .arg("-m").arg("1024")
+ .arg("-kernel").arg("/tmp/zImage")
+ .arg("-initrd").arg(&rootfs_img)
+ .arg("-dtb").arg("/tmp/vexpress-v2p-ca15-tc1.dtb")
+ .arg("-append").arg("console=ttyAMA0 root=/dev/ram rdinit=/sbin/init init=/sbin/init")
+ .arg("-nographic")
+ .arg("-redir").arg("tcp:12345::12345");
+ t!(cmd.spawn());
+
+ // Wait for the emulator to come online
+ loop {
+ let dur = Duration::from_millis(100);
+ if let Ok(mut client) = TcpStream::connect("127.0.0.1:12345") {
+ t!(client.set_read_timeout(Some(dur)));
+ t!(client.set_write_timeout(Some(dur)));
+ if client.write_all(b"ping").is_ok() {
+ let mut b = [0; 4];
+ if client.read_exact(&mut b).is_ok() {
+ break
+ }
+ }
+ }
+ thread::sleep(dur);
+ }
+
+ fn add_files(w: &mut Write, root: &Path, cur: &Path) {
+ for entry in t!(cur.read_dir()) {
+ let entry = t!(entry);
+ let path = entry.path();
+ let to_print = path.strip_prefix(root).unwrap();
+ t!(write!(w, "{}\u{0}", to_print.to_str().unwrap()));
+ if t!(entry.file_type()).is_dir() {
+ add_files(w, root, &path);
+ }
+ }
+ }
+}
+
+fn push(path: &Path) {
+ let client = t!(TcpStream::connect("127.0.0.1:12345"));
+ let mut client = BufWriter::new(client);
+ t!(client.write_all(b"push"));
+ t!(client.write_all(path.file_name().unwrap().to_str().unwrap().as_bytes()));
+ t!(client.write_all(&[0]));
+ let mut file = t!(File::open(path));
+ t!(io::copy(&mut file, &mut client));
+ t!(client.flush());
+ println!("done pushing {:?}", path);
+}
+
+fn run(files: String, args: Vec<String>) {
+ let client = t!(TcpStream::connect("127.0.0.1:12345"));
+ let mut client = BufWriter::new(client);
+ t!(client.write_all(b"run "));
+
+ // Send over the args
+ for arg in args {
+ t!(client.write_all(arg.as_bytes()));
+ t!(client.write_all(&[0]));
+ }
+ t!(client.write_all(&[0]));
+
+ // Send over env vars
+ for (k, v) in env::vars() {
+ if k != "PATH" && k != "LD_LIBRARY_PATH" {
+ t!(client.write_all(k.as_bytes()));
+ t!(client.write_all(&[0]));
+ t!(client.write_all(v.as_bytes()));
+ t!(client.write_all(&[0]));
+ }
+ }
+ t!(client.write_all(&[0]));
+
+ // Send over support libraries
+ let mut files = files.split(':');
+ let exe = files.next().unwrap();
+ for file in files.map(Path::new) {
+ t!(client.write_all(file.file_name().unwrap().to_str().unwrap().as_bytes()));
+ t!(client.write_all(&[0]));
+ send(&file, &mut client);
+ }
+ t!(client.write_all(&[0]));
+
+ // Send over the client executable as the last piece
+ send(exe.as_ref(), &mut client);
+
+ println!("uploaded {:?}, waiting for result", exe);
+
+ // Ok now it's time to read all the output. We're receiving "frames"
+ // representing stdout/stderr, so we decode all that here.
+ let mut header = [0; 5];
+ let mut stderr_done = false;
+ let mut stdout_done = false;
+ let mut client = t!(client.into_inner());
+ let mut stdout = io::stdout();
+ let mut stderr = io::stderr();
+ while !stdout_done || !stderr_done {
+ t!(client.read_exact(&mut header));
+ let amt = ((header[1] as u64) << 24) |
+ ((header[2] as u64) << 16) |
+ ((header[3] as u64) << 8) |
+ ((header[4] as u64) << 0);
+ if header[0] == 0 {
+ if amt == 0 {
+ stdout_done = true;
+ } else {
+ t!(io::copy(&mut (&mut client).take(amt), &mut stdout));
+ t!(stdout.flush());
+ }
+ } else {
+ if amt == 0 {
+ stderr_done = true;
+ } else {
+ t!(io::copy(&mut (&mut client).take(amt), &mut stderr));
+ t!(stderr.flush());
+ }
+ }
+ }
+
+ // Finally, read out the exit status
+ let mut status = [0; 5];
+ t!(client.read_exact(&mut status));
+ let code = ((status[1] as i32) << 24) |
+ ((status[2] as i32) << 16) |
+ ((status[3] as i32) << 8) |
+ ((status[4] as i32) << 0);
+ if status[0] == 0 {
+ std::process::exit(code);
+ } else {
+ println!("died due to signal {}", code);
+ std::process::exit(3);
+ }
+}
+
+fn send(path: &Path, dst: &mut Write) {
+ let mut file = t!(File::open(&path));
+ let amt = t!(file.metadata()).len();
+ t!(dst.write_all(&[
+ (amt >> 24) as u8,
+ (amt >> 16) as u8,
+ (amt >> 8) as u8,
+ (amt >> 0) as u8,
+ ]));
+ t!(io::copy(&mut file, dst));
+}
--- /dev/null
+[package]
+name = "qemu-test-server"
+version = "0.1.0"
+authors = ["The Rust Project Developers"]
+
+[dependencies]
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// This is a small server which is intended to run inside of an emulator. This
+/// server pairs with the `qemu-test-client` program in this repository. The
+/// `qemu-test-client` connects to this server over a TCP socket and performs
+/// work such as:
+///
+/// 1. Pushing shared libraries to the server
+/// 2. Running tests through the server
+///
+/// The server supports running tests concurrently and also supports tests
+/// themselves having support libraries. All data over the TCP sockets is in a
+/// basically custom format suiting our needs.
+
+use std::fs::{self, File, Permissions};
+use std::io::prelude::*;
+use std::io::{self, BufReader};
+use std::net::{TcpListener, TcpStream};
+use std::os::unix::prelude::*;
+use std::sync::{Arc, Mutex};
+use std::path::Path;
+use std::str;
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+use std::thread;
+use std::process::{Command, Stdio};
+
+macro_rules! t {
+ ($e:expr) => (match $e {
+ Ok(e) => e,
+ Err(e) => panic!("{} failed with {}", stringify!($e), e),
+ })
+}
+
+static TEST: AtomicUsize = ATOMIC_USIZE_INIT;
+
+fn main() {
+ println!("starting test server");
+ let listener = t!(TcpListener::bind("10.0.2.15:12345"));
+ println!("listening!");
+
+ let work = Path::new("/tmp/work");
+ t!(fs::create_dir_all(work));
+
+ let lock = Arc::new(Mutex::new(()));
+
+ for socket in listener.incoming() {
+ let mut socket = t!(socket);
+ let mut buf = [0; 4];
+ t!(socket.read_exact(&mut buf));
+ if &buf[..] == b"ping" {
+ t!(socket.write_all(b"pong"));
+ } else if &buf[..] == b"push" {
+ handle_push(socket, work);
+ } else if &buf[..] == b"run " {
+ let lock = lock.clone();
+ thread::spawn(move || handle_run(socket, work, &lock));
+ } else {
+ panic!("unknown command {:?}", buf);
+ }
+ }
+}
+
+fn handle_push(socket: TcpStream, work: &Path) {
+ let mut reader = BufReader::new(socket);
+ let mut filename = Vec::new();
+ t!(reader.read_until(0, &mut filename));
+ filename.pop(); // chop off the 0
+ let filename = t!(str::from_utf8(&filename));
+
+ let path = work.join(filename);
+ t!(io::copy(&mut reader, &mut t!(File::create(&path))));
+ t!(fs::set_permissions(&path, Permissions::from_mode(0o755)));
+}
+
+struct RemoveOnDrop<'a> {
+ inner: &'a Path,
+}
+
+impl<'a> Drop for RemoveOnDrop<'a> {
+ fn drop(&mut self) {
+ t!(fs::remove_dir_all(self.inner));
+ }
+}
+
+fn handle_run(socket: TcpStream, work: &Path, lock: &Mutex<()>) {
+ let mut arg = Vec::new();
+ let mut reader = BufReader::new(socket);
+
+ // Allocate ourselves a directory that we'll delete when we're done to save
+ // space.
+ let n = TEST.fetch_add(1, Ordering::SeqCst);
+ let path = work.join(format!("test{}", n));
+ let exe = path.join("exe");
+ t!(fs::create_dir(&path));
+ let _a = RemoveOnDrop { inner: &path };
+
+ // First up we'll get a list of arguments delimited with 0 bytes. An empty
+ // argument means that we're done.
+ let mut cmd = Command::new(&exe);
+ while t!(reader.read_until(0, &mut arg)) > 1 {
+ cmd.arg(t!(str::from_utf8(&arg[..arg.len() - 1])));
+ arg.truncate(0);
+ }
+
+ // Next we'll get a bunch of env vars in pairs delimited by 0s as well
+ arg.truncate(0);
+ while t!(reader.read_until(0, &mut arg)) > 1 {
+ let key_len = arg.len() - 1;
+ let val_len = t!(reader.read_until(0, &mut arg)) - 1;
+ {
+ let key = &arg[..key_len];
+ let val = &arg[key_len + 1..][..val_len];
+ let key = t!(str::from_utf8(key));
+ let val = t!(str::from_utf8(val));
+ cmd.env(key, val);
+ }
+ arg.truncate(0);
+ }
+
+ // The section of code from here down to where we drop the lock is going to
+ // be a critical section for us. On Linux you can't execute a file which is
+ // open somewhere for writing, as you'll receive the error "text file busy".
+ // Now here we never have the text file open for writing when we spawn it,
+ // so why do we still need a critical section?
+ //
+ // Process spawning first involves a `fork` on Unix, which clones all file
+ // descriptors into the child process. This means that it's possible for us
+ // to open the file for writing (as we're downloading it), then some other
+ // thread forks, then we close the file and try to exec. At that point the
+ // other thread created a child process with the file open for writing, and
+ // we attempt to execute it, so we get an error.
+ //
+ // This race is resolve by ensuring that only one thread can writ ethe file
+ // and spawn a child process at once. Kinda an unfortunate solution, but we
+ // don't have many other choices with this sort of setup!
+ //
+ // In any case the lock is acquired here, before we start writing any files.
+ // It's then dropped just after we spawn the child. That way we don't lock
+ // the execution of the child, just the creation of its files.
+ let lock = lock.lock();
+
+ // Next there's a list of dynamic libraries preceded by their filenames.
+ arg.truncate(0);
+ while t!(reader.read_until(0, &mut arg)) > 1 {
+ let dst = path.join(t!(str::from_utf8(&arg[..arg.len() - 1])));
+ let amt = read_u32(&mut reader) as u64;
+ t!(io::copy(&mut reader.by_ref().take(amt),
+ &mut t!(File::create(&dst))));
+ t!(fs::set_permissions(&dst, Permissions::from_mode(0o755)));
+ arg.truncate(0);
+ }
+
+ // Finally we'll get the binary. The other end will tell us how big the
+ // binary is and then we'll download it all to the exe path we calculated
+ // earlier.
+ let amt = read_u32(&mut reader) as u64;
+ t!(io::copy(&mut reader.by_ref().take(amt),
+ &mut t!(File::create(&exe))));
+ t!(fs::set_permissions(&exe, Permissions::from_mode(0o755)));
+
+ // Support libraries were uploaded to `work` earlier, so make sure that's
+ // in `LD_LIBRARY_PATH`. Also include our own current dir which may have
+ // had some libs uploaded.
+ cmd.env("LD_LIBRARY_PATH",
+ format!("{}:{}", work.display(), path.display()));
+
+ // Spawn the child and ferry over stdout/stderr to the socket in a framed
+ // fashion (poor man's style)
+ let mut child = t!(cmd.stdin(Stdio::null())
+ .stdout(Stdio::piped())
+ .stderr(Stdio::piped())
+ .spawn());
+ drop(lock);
+ let mut stdout = child.stdout.take().unwrap();
+ let mut stderr = child.stderr.take().unwrap();
+ let socket = Arc::new(Mutex::new(reader.into_inner()));
+ let socket2 = socket.clone();
+ let thread = thread::spawn(move || my_copy(&mut stdout, 0, &*socket2));
+ my_copy(&mut stderr, 1, &*socket);
+ thread.join().unwrap();
+
+ // Finally send over the exit status.
+ let status = t!(child.wait());
+ let (which, code) = match status.code() {
+ Some(n) => (0, n),
+ None => (1, status.signal().unwrap()),
+ };
+ t!(socket.lock().unwrap().write_all(&[
+ which,
+ (code >> 24) as u8,
+ (code >> 16) as u8,
+ (code >> 8) as u8,
+ (code >> 0) as u8,
+ ]));
+}
+
+fn my_copy(src: &mut Read, which: u8, dst: &Mutex<Write>) {
+ let mut b = [0; 1024];
+ loop {
+ let n = t!(src.read(&mut b));
+ let mut dst = dst.lock().unwrap();
+ t!(dst.write_all(&[
+ which,
+ (n >> 24) as u8,
+ (n >> 16) as u8,
+ (n >> 8) as u8,
+ (n >> 0) as u8,
+ ]));
+ if n > 0 {
+ t!(dst.write_all(&b[..n]));
+ } else {
+ break
+ }
+ }
+}
+
+fn read_u32(r: &mut Read) -> u32 {
+ let mut len = [0; 4];
+ t!(r.read_exact(&mut len));
+ ((len[0] as u32) << 24) |
+ ((len[1] as u32) << 16) |
+ ((len[2] as u32) << 8) |
+ ((len[3] as u32) << 0)
+}