diff --git a/config.toml.example b/config.toml.example index c2ec731eeb8..f153562a538 100644 --- a/config.toml.example +++ b/config.toml.example @@ -151,6 +151,10 @@ # default. #extended = false +# Installs choosen set of extended tools if enables. By default builds all. +# If choosen tool failed to build the installation fails. +#tools = ["cargo", "rls", "rustfmt", "analysis", "src"] + # Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose #verbose = 0 diff --git a/src/binaryen b/src/binaryen index 1c9bf65aa0e..17841e155ed 160000 --- a/src/binaryen +++ b/src/binaryen @@ -1 +1 @@ -Subproject commit 1c9bf65aa0e371b84755a8ddd6e79497fac57171 +Subproject commit 17841e155edf858c8ea7802dd5f5ecbef54b989f diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 6c68ee18506..74dd4a6fa01 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -570,7 +570,7 @@ impl<'a> Builder<'a> { // build scripts in that situation. // // If LLVM support is disabled we need to use the snapshot compiler to compile - // build scripts, as the new compiler doesnt support executables. + // build scripts, as the new compiler doesn't support executables. if mode == Mode::Libstd || !self.build.config.llvm_enabled { cargo.env("RUSTC_SNAPSHOT", &self.initial_rustc) .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir()); @@ -600,9 +600,25 @@ impl<'a> Builder<'a> { // // FIXME: the guard against msvc shouldn't need to be here if !target.contains("msvc") { - let cc = self.cc(target); - cargo.env(format!("CC_{}", target), cc) - .env("CC", cc); + let ccache = self.config.ccache.as_ref(); + let ccacheify = |s: &Path| { + let ccache = match ccache { + Some(ref s) => s, + None => return s.display().to_string(), + }; + // FIXME: the cc-rs crate only recognizes the literal strings + // `ccache` and `sccache` when doing caching compilations, so we + // mirror that here. It should probably be fixed upstream to + // accept a new env var or otherwise work with custom ccache + // vars. + match &ccache[..] { + "ccache" | "sccache" => format!("{} {}", ccache, s.display()), + _ => s.display().to_string(), + } + }; + let cc = ccacheify(&self.cc(target)); + cargo.env(format!("CC_{}", target), &cc) + .env("CC", &cc); let cflags = self.cflags(target).join(" "); cargo.env(format!("CFLAGS_{}", target), cflags.clone()) @@ -617,8 +633,9 @@ impl<'a> Builder<'a> { } if let Ok(cxx) = self.cxx(target) { - cargo.env(format!("CXX_{}", target), cxx) - .env("CXX", cxx) + let cxx = ccacheify(&cxx); + cargo.env(format!("CXX_{}", target), &cxx) + .env("CXX", &cxx) .env(format!("CXXFLAGS_{}", target), cflags.clone()) .env("CXXFLAGS", cflags); } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index be8910120ee..4f4fd14ae8c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -13,7 +13,7 @@ //! This module implements parsing `config.toml` configuration files to tweak //! how the build runs. -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::env; use std::fs::File; use std::io::prelude::*; @@ -52,6 +52,7 @@ pub struct Config { pub target_config: HashMap, Target>, pub full_bootstrap: bool, pub extended: bool, + pub tools: Option>, pub sanitizers: bool, pub profiler: bool, pub ignore_git: bool, @@ -191,6 +192,7 @@ struct Build { python: Option, full_bootstrap: Option, extended: Option, + tools: Option>, verbose: Option, sanitizers: Option, profiler: Option, @@ -395,6 +397,7 @@ impl Config { set(&mut config.vendor, build.vendor); set(&mut config.full_bootstrap, build.full_bootstrap); set(&mut config.extended, build.extended); + config.tools = build.tools; set(&mut config.verbose, build.verbose); set(&mut config.sanitizers, build.sanitizers); set(&mut config.profiler, build.profiler); diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index d51752a12d9..99a3ee4e4c3 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -144,6 +144,7 @@ o("jemalloc", "rust.use-jemalloc", "build liballoc with jemalloc") o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two") o("extended", "build.extended", "build an extended rust tool set") +v("tools", "build.tools", "List of extended tools will be installed") v("build", "build.build", "GNUs ./configure syntax LLVM build triple") v("host", None, "GNUs ./configure syntax LLVM host triples") v("target", None, "GNUs ./configure syntax LLVM target triples") diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 6717b1cb098..460fb016f16 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -31,6 +31,7 @@ use channel; use util::{cp_r, libdir, is_dylib, cp_filtered, copy, replace_in_file}; use builder::{Builder, RunConfig, ShouldRun, Step}; use compile; +use native; use tool::{self, Tool}; use cache::{INTERNER, Interned}; use time; @@ -898,6 +899,12 @@ impl Step for PlainSourceTarball { .arg("--vers").arg(CARGO_VENDOR_VERSION) .arg("cargo-vendor") .env("RUSTC", &build.initial_rustc); + if let Some(dir) = build.openssl_install_dir(build.config.build) { + builder.ensure(native::Openssl { + target: build.config.build, + }); + cmd.env("OPENSSL_DIR", dir); + } build.run(&mut cmd); } diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 743f32ece99..20f7d379a69 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -22,6 +22,7 @@ use dist::{self, pkgname, sanitize_sh, tmpdir}; use builder::{Builder, RunConfig, ShouldRun, Step}; use cache::Interned; +use config::Config; pub fn install_docs(builder: &Builder, stage: u32, host: Interned) { install_sh(builder, "docs", "rust-docs", stage, Some(host)); @@ -144,6 +145,19 @@ macro_rules! install { pub host: Interned, } + impl $name { + #[allow(dead_code)] + fn should_build(config: &Config) -> bool { + config.extended && config.tools.as_ref() + .map_or(true, |t| t.contains($path)) + } + + #[allow(dead_code)] + fn should_install(builder: &Builder) -> bool { + builder.config.tools.as_ref().map_or(false, |t| t.contains($path)) + } + } + impl Step for $name { type Output = (); const DEFAULT: bool = true; @@ -185,32 +199,34 @@ install!((self, builder, _config), install_std(builder, self.stage, *target); } }; - Cargo, "cargo", _config.extended, only_hosts: true, { + Cargo, "cargo", Self::should_build(_config), only_hosts: true, { builder.ensure(dist::Cargo { stage: self.stage, target: self.target }); install_cargo(builder, self.stage, self.target); }; - Rls, "rls", _config.extended, only_hosts: true, { - if builder.ensure(dist::Rls { stage: self.stage, target: self.target }).is_some() { + Rls, "rls", Self::should_build(_config), only_hosts: true, { + if builder.ensure(dist::Rls { stage: self.stage, target: self.target }).is_some() || + Self::should_install(builder) { install_rls(builder, self.stage, self.target); } else { println!("skipping Install RLS stage{} ({})", self.stage, self.target); } }; - Rustfmt, "rustfmt", _config.extended, only_hosts: true, { - if builder.ensure(dist::Rustfmt { stage: self.stage, target: self.target }).is_some() { + Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, { + if builder.ensure(dist::Rustfmt { stage: self.stage, target: self.target }).is_some() || + Self::should_install(builder) { install_rustfmt(builder, self.stage, self.target); } else { println!("skipping Install Rustfmt stage{} ({})", self.stage, self.target); } }; - Analysis, "analysis", _config.extended, only_hosts: false, { + Analysis, "analysis", Self::should_build(_config), only_hosts: false, { builder.ensure(dist::Analysis { compiler: builder.compiler(self.stage, self.host), target: self.target }); install_analysis(builder, self.stage, self.target); }; - Src, "src", _config.extended, only_hosts: true, { + Src, "src", Self::should_build(_config) , only_hosts: true, { builder.ensure(dist::Src); install_src(builder, self.stage); }, ONLY_BUILD; diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index a84a6a8990b..83c270865c0 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -666,7 +666,7 @@ impl Build { } } - /// Returns the path to the linker for the given target if it needs to be overriden. + /// Returns the path to the linker for the given target if it needs to be overridden. fn linker(&self, target: Interned) -> Option<&Path> { if let Some(linker) = self.config.target_config.get(&target) .and_then(|c| c.linker.as_ref()) { diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index eae8ec1311d..f6b95f0bf97 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -902,7 +902,7 @@ impl Step for Compiletest { } } if suite == "run-make" && !build.config.llvm_enabled { - println!("Ignoring run-make test suite as they generally dont work without LLVM"); + println!("Ignoring run-make test suite as they generally don't work without LLVM"); return; } diff --git a/src/ci/docker/dist-i686-linux/Dockerfile b/src/ci/docker/dist-i686-linux/Dockerfile index 0fd6af6e10d..5e405aa72e8 100644 --- a/src/ci/docker/dist-i686-linux/Dockerfile +++ b/src/ci/docker/dist-i686-linux/Dockerfile @@ -86,7 +86,8 @@ ENV RUST_CONFIGURE_ARGS \ --enable-extended \ --enable-sanitizers \ --enable-profiler \ - --enable-emscripten + --enable-emscripten \ + --build=i686-unknown-linux-gnu ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS # This is the only builder which will create source tarballs diff --git a/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh b/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh index 5b4314d57e6..e730dd86087 100755 --- a/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh +++ b/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh @@ -54,7 +54,7 @@ cd usr/src # The options, in order, do the following # * this is an unprivileged build # * output to a predictable location -# * disable various uneeded stuff +# * disable various unneeded stuff MKUNPRIVED=yes TOOLDIR=/x-tools/x86_64-unknown-netbsd \ MKSHARE=no MKDOC=no MKHTML=no MKINFO=no MKKMOD=no MKLINT=no MKMAN=no MKNLS=no MKPROFILE=no \ hide_output ./build.sh -j10 -m amd64 tools diff --git a/src/dlmalloc b/src/dlmalloc index a2b424b6002..9b2dcac06c3 160000 --- a/src/dlmalloc +++ b/src/dlmalloc @@ -1 +1 @@ -Subproject commit a2b424b600235af58f453577c2da1b0e1de2ffa5 +Subproject commit 9b2dcac06c3e23235f8997b3c5f2325a6d3382df diff --git a/src/doc/book b/src/doc/book index a645960fe48..ec5660820de 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit a645960fe48946153936dd5628df4a90bd837981 +Subproject commit ec5660820dea91df470dab0b9eb26ef798f20889 diff --git a/src/doc/nomicon b/src/doc/nomicon index fec3182d0b0..ad5ddd62c09 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit fec3182d0b0a3cf8122e192b3270064a5b19be5b +Subproject commit ad5ddd62c098d5b424151beda574ae7df2154df1 diff --git a/src/doc/reference b/src/doc/reference index e6a5d5d10aa..254df654a9b 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit e6a5d5d10aa2fde0baed7b29bf672bd9f3af8962 +Subproject commit 254df654a9b75abf6ca08806535dbe1fad41be3f diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 4ebb8169dfe..919980be7df 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 4ebb8169dfe569b3dcbeab560607800bb717978a +Subproject commit 919980be7df4ea7d45a9dca8efc34da89bcf7d6b diff --git a/src/etc/installer/msi/rust.wxs b/src/etc/installer/msi/rust.wxs index d95b096d732..a471ccc6f5b 100644 --- a/src/etc/installer/msi/rust.wxs +++ b/src/etc/installer/msi/rust.wxs @@ -18,7 +18,7 @@ - + @@ -129,7 +129,7 @@ - + diff --git a/src/etc/platform-intrinsics/generator.py b/src/etc/platform-intrinsics/generator.py index e9cf71c32fe..d9f78978a25 100644 --- a/src/etc/platform-intrinsics/generator.py +++ b/src/etc/platform-intrinsics/generator.py @@ -591,7 +591,7 @@ def parse_args(): The X86 architecture is specified as multiple files (for the different instruction sets that x86 supports). To generate the compiler definitions one needs to pass the script a "platform information file" - (with the -i flag) next to the files of the different intruction sets. + (with the -i flag) next to the files of the different instruction sets. For example, to generate the X86 compiler-definitions for SSE4.2, just: python generator.py --format compiler-defs -i x86/info.json sse42.json diff --git a/src/etc/test-float-parse/runtests.py b/src/etc/test-float-parse/runtests.py index d520c9bd5c3..e9f5bba2312 100644 --- a/src/etc/test-float-parse/runtests.py +++ b/src/etc/test-float-parse/runtests.py @@ -41,7 +41,7 @@ Instead, we take the input and compute the true value with bignum arithmetic (as a fraction, using the ``fractions`` module). Given an input string and the corresponding float computed via Rust, simply -decode the float into f * 2^k (for intergers f, k) and the ULP. +decode the float into f * 2^k (for integers f, k) and the ULP. We can now easily compute the error and check if it is within 0.5 ULP as it should be. Zero and infinites are handled similarly: diff --git a/src/libbacktrace/ltmain.sh b/src/libbacktrace/ltmain.sh index eff9e62be8a..fd23815fc61 100644 --- a/src/libbacktrace/ltmain.sh +++ b/src/libbacktrace/ltmain.sh @@ -487,7 +487,7 @@ func_mkdir_p () # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited - # list incase some portion of path contains whitespace. + # list in case some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done diff --git a/src/libbacktrace/macho.c b/src/libbacktrace/macho.c index 9af14e724b4..ba7f94c079f 100644 --- a/src/libbacktrace/macho.c +++ b/src/libbacktrace/macho.c @@ -327,7 +327,7 @@ macho_get_commands (struct backtrace_state *state, int descriptor, goto end; file_header_view_valid = 1; - // The endianess of the slice may be different than the fat image + // The endianness of the slice may be different than the fat image switch (*(uint32_t *) file_header_view.data) { case MH_MAGIC: diff --git a/src/libcore/char.rs b/src/libcore/char.rs index e8b81db0706..7215bd2a476 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -211,7 +211,7 @@ impl From for char { /// An error which can be returned when parsing a char. #[stable(feature = "char_from_str", since = "1.20.0")] -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct ParseCharError { kind: CharErrorKind, } diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 296fb8733ba..33adb3f49dd 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1431,6 +1431,10 @@ pub trait Iterator { /// Folding is useful whenever you have a collection of something, and want /// to produce a single value from it. /// + /// Note: `fold()`, and similar methods that traverse the entire iterator, + /// may not terminate for infinite iterators, even on traits for which a + /// result is determinable in finite time. + /// /// # Examples /// /// Basic usage: diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index bf8367d85fd..29b62c901f3 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -298,7 +298,21 @@ //! //! This will print the numbers `0` through `4`, each on their own line. //! +//! Bear in mind that methods on infinite iterators, even those for which a +//! result can be determined mathematically in finite time, may not terminate. +//! Specifically, methods such as [`min`], which in the general case require +//! traversing every element in the iterator, are likely not to return +//! successfully for any infinite iterators. +//! +//! ```no_run +//! let ones = std::iter::repeat(1); +//! let least = ones.min().unwrap(); // Oh no! An infinite loop! +//! // `ones.min()` causes an infinite loop, so we won't reach this point! +//! println!("The smallest number one is {}.", least); +//! ``` +//! //! [`take`]: trait.Iterator.html#method.take +//! [`min`]: trait.Iterator.html#method.min #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index f00128a8147..cc5cf6523a9 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -327,7 +327,7 @@ macro_rules! debug_assert_ne { /// } /// } /// -/// // The prefered method of quick returning Errors +/// // The preferred method of quick returning Errors /// fn write_to_file_question() -> Result<(), MyError> { /// let mut file = File::create("my_best_friends.txt")?; /// file.write_all(b"This is a list of my best friends.")?; diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs index d0d0c09869e..88db019b02f 100644 --- a/src/libcore/ops/arith.rs +++ b/src/libcore/ops/arith.rs @@ -181,7 +181,7 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "sub"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented(message="cannot substract `{RHS}` from `{Self}`", +#[rustc_on_unimplemented(message="cannot subtract `{RHS}` from `{Self}`", label="no implementation for `{Self} - {RHS}`")] pub trait Sub { /// The resulting type after applying the `-` operator. @@ -716,7 +716,7 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "sub_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented(message="cannot substract-assign `{Rhs}` from `{Self}`", +#[rustc_on_unimplemented(message="cannot subtract-assign `{Rhs}` from `{Self}`", label="no implementation for `{Self} -= {Rhs}`")] pub trait SubAssign { /// Performs the `-=` operation. diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 8b47143f63c..f22862ae701 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -945,6 +945,7 @@ macro_rules! atomic_int { $stable_debug:meta, $stable_access:meta, $stable_from:meta, + $stable_nand:meta, $s_int_type:expr, $int_ref:expr, $int_type:ident $atomic_type:ident $atomic_init:ident) => { /// An integer type which can be safely shared between threads. @@ -1325,6 +1326,29 @@ macro_rules! atomic_int { unsafe { atomic_and(self.v.get(), val, order) } } + /// Bitwise "nand" with the current value. + /// + /// Performs a bitwise "nand" operation on the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_nand)] + /// + /// use std::sync::atomic::{AtomicIsize, Ordering}; + /// + /// let foo = AtomicIsize::new(0xf731); + /// assert_eq!(foo.fetch_nand(0x137f, Ordering::SeqCst), 0xf731); + /// assert_eq!(foo.load(Ordering::SeqCst), !(0xf731 & 0x137f)); + #[inline] + #[$stable_nand] + pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_nand(self.v.get(), val, order) } + } + /// Bitwise "or" with the current value. /// /// Performs a bitwise "or" operation on the current value and the argument `val`, and @@ -1377,6 +1401,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "i8", "../../../std/primitive.i8.html", i8 AtomicI8 ATOMIC_I8_INIT } @@ -1387,6 +1412,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "u8", "../../../std/primitive.u8.html", u8 AtomicU8 ATOMIC_U8_INIT } @@ -1397,6 +1423,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "i16", "../../../std/primitive.i16.html", i16 AtomicI16 ATOMIC_I16_INIT } @@ -1407,6 +1434,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "u16", "../../../std/primitive.u16.html", u16 AtomicU16 ATOMIC_U16_INIT } @@ -1417,6 +1445,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "i32", "../../../std/primitive.i32.html", i32 AtomicI32 ATOMIC_I32_INIT } @@ -1427,6 +1456,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "u32", "../../../std/primitive.u32.html", u32 AtomicU32 ATOMIC_U32_INIT } @@ -1437,6 +1467,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "i64", "../../../std/primitive.i64.html", i64 AtomicI64 ATOMIC_I64_INIT } @@ -1447,6 +1478,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "atomic_nand", issue = "13226"), "u64", "../../../std/primitive.u64.html", u64 AtomicU64 ATOMIC_U64_INIT } @@ -1457,6 +1489,7 @@ atomic_int!{ stable(feature = "atomic_debug", since = "1.3.0"), stable(feature = "atomic_access", since = "1.15.0"), stable(feature = "atomic_from", since = "1.23.0"), + unstable(feature = "atomic_nand", issue = "13226"), "isize", "../../../std/primitive.isize.html", isize AtomicIsize ATOMIC_ISIZE_INIT } @@ -1467,6 +1500,7 @@ atomic_int!{ stable(feature = "atomic_debug", since = "1.3.0"), stable(feature = "atomic_access", since = "1.15.0"), stable(feature = "atomic_from", since = "1.23.0"), + unstable(feature = "atomic_nand", issue = "13226"), "usize", "../../../std/primitive.usize.html", usize AtomicUsize ATOMIC_USIZE_INIT } @@ -1609,6 +1643,18 @@ unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { } } +#[inline] +unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { + match order { + Acquire => intrinsics::atomic_nand_acq(dst, val), + Release => intrinsics::atomic_nand_rel(dst, val), + AcqRel => intrinsics::atomic_nand_acqrel(dst, val), + Relaxed => intrinsics::atomic_nand_relaxed(dst, val), + SeqCst => intrinsics::atomic_nand(dst, val), + __Nonexhaustive => panic!("invalid memory ordering"), + } +} + #[inline] unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { match order { diff --git a/src/libcore/tests/atomic.rs b/src/libcore/tests/atomic.rs index 9babe24a985..f634fabe503 100644 --- a/src/libcore/tests/atomic.rs +++ b/src/libcore/tests/atomic.rs @@ -48,6 +48,13 @@ fn uint_and() { assert_eq!(x.load(SeqCst), 0xf731 & 0x137f); } +#[test] +fn uint_nand() { + let x = AtomicUsize::new(0xf731); + assert_eq!(x.fetch_nand(0x137f, SeqCst), 0xf731); + assert_eq!(x.load(SeqCst), !(0xf731 & 0x137f)); +} + #[test] fn uint_or() { let x = AtomicUsize::new(0xf731); @@ -69,6 +76,13 @@ fn int_and() { assert_eq!(x.load(SeqCst), 0xf731 & 0x137f); } +#[test] +fn int_nand() { + let x = AtomicIsize::new(0xf731); + assert_eq!(x.fetch_nand(0x137f, SeqCst), 0xf731); + assert_eq!(x.load(SeqCst), !(0xf731 & 0x137f)); +} + #[test] fn int_or() { let x = AtomicIsize::new(0xf731); diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 1c32452f846..9e90313bc0e 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -42,6 +42,7 @@ #![feature(try_from)] #![feature(try_trait)] #![feature(exact_chunks)] +#![feature(atomic_nand)] extern crate core; extern crate test; diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 44cdb5e8a36..71519ab21fe 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -73,7 +73,7 @@ pub struct FormatSpec<'a> { /// Enum describing where an argument for a format can be located. #[derive(Copy, Clone, PartialEq)] pub enum Position<'a> { - /// The arugment is implied to be located at an index + /// The argument is implied to be located at an index ArgumentImplicitlyIs(usize), /// The argument is located at a specific index given in the format ArgumentIs(usize), diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 97cf9b01410..b804cf7bf5a 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -965,8 +965,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { walk_list!(visitor, visit_expr, subexpressions); } ExprCall(ref callee_expression, ref arguments) => { + visitor.visit_expr(callee_expression); walk_list!(visitor, visit_expr, arguments); - visitor.visit_expr(callee_expression) } ExprMethodCall(ref segment, _, ref arguments) => { visitor.visit_path_segment(expression.span, segment); diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index d4bcf00be80..a290839425e 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -764,8 +764,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } else { let (closure_span, found) = found_did .and_then(|did| self.tcx.hir.get_if_local(did)) - .map(|node| self.get_fn_like_arguments(node)) - .unwrap_or((found_span.unwrap(), found)); + .map(|node| { + let (found_span, found) = self.get_fn_like_arguments(node); + (Some(found_span), found) + }).unwrap_or((found_span, found)); self.report_arg_count_mismatch(span, closure_span, @@ -875,7 +877,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fn report_arg_count_mismatch( &self, span: Span, - found_span: Span, + found_span: Option, expected_args: Vec, found_args: Vec, is_closure: bool, @@ -913,48 +915,51 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ); err.span_label(span, format!( "expected {} that takes {}", kind, expected_str)); - err.span_label(found_span, format!("takes {}", found_str)); - if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] { - if fields.len() == expected_args.len() { - let sugg = fields.iter() - .map(|(name, _)| name.to_owned()) - .collect::>().join(", "); - err.span_suggestion(found_span, - "change the closure to take multiple arguments instead of \ - a single tuple", - format!("|{}|", sugg)); + if let Some(found_span) = found_span { + err.span_label(found_span, format!("takes {}", found_str)); + + if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] { + if fields.len() == expected_args.len() { + let sugg = fields.iter() + .map(|(name, _)| name.to_owned()) + .collect::>().join(", "); + err.span_suggestion(found_span, + "change the closure to take multiple arguments instead of \ + a single tuple", + format!("|{}|", sugg)); + } } - } - if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] { - if fields.len() == found_args.len() && is_closure { - let sugg = format!( - "|({}){}|", - found_args.iter() - .map(|arg| match arg { - ArgKind::Arg(name, _) => name.to_owned(), - _ => "_".to_owned(), - }) - .collect::>() - .join(", "), - // add type annotations if available - if found_args.iter().any(|arg| match arg { - ArgKind::Arg(_, ty) => ty != "_", - _ => false, - }) { - format!(": ({})", - fields.iter() - .map(|(_, ty)| ty.to_owned()) - .collect::>() - .join(", ")) - } else { - "".to_owned() - }, - ); - err.span_suggestion(found_span, - "change the closure to accept a tuple instead of individual \ - arguments", - sugg); + if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] { + if fields.len() == found_args.len() && is_closure { + let sugg = format!( + "|({}){}|", + found_args.iter() + .map(|arg| match arg { + ArgKind::Arg(name, _) => name.to_owned(), + _ => "_".to_owned(), + }) + .collect::>() + .join(", "), + // add type annotations if available + if found_args.iter().any(|arg| match arg { + ArgKind::Arg(_, ty) => ty != "_", + _ => false, + }) { + format!(": ({})", + fields.iter() + .map(|(_, ty)| ty.to_owned()) + .collect::>() + .join(", ")) + } else { + "".to_owned() + }, + ); + err.span_suggestion(found_span, + "change the closure to accept a tuple instead of \ + individual arguments", + sugg); + } } } diff --git a/src/librustc_data_structures/blake2b.rs b/src/librustc_data_structures/blake2b.rs deleted file mode 100644 index 6b8bf8df0d3..00000000000 --- a/src/librustc_data_structures/blake2b.rs +++ /dev/null @@ -1,363 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -// An implementation of the Blake2b cryptographic hash function. -// The implementation closely follows: https://tools.ietf.org/html/rfc7693 -// -// "BLAKE2 is a cryptographic hash function faster than MD5, SHA-1, SHA-2, and -// SHA-3, yet is at least as secure as the latest standard SHA-3." -// according to their own website :) -// -// Indeed this implementation is two to three times as fast as our SHA-256 -// implementation. If you have the luxury of being able to use crates from -// crates.io, you can go there and find still faster implementations. - -use std::mem; -use std::slice; - -#[repr(C)] -struct Blake2bCtx { - b: [u8; 128], - h: [u64; 8], - t: [u64; 2], - c: usize, - outlen: u16, - finalized: bool, - - #[cfg(debug_assertions)] - fnv_hash: u64, -} - -#[cfg(debug_assertions)] -impl ::std::fmt::Debug for Blake2bCtx { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(fmt, "{:x}", self.fnv_hash) - } -} - -#[cfg(not(debug_assertions))] -impl ::std::fmt::Debug for Blake2bCtx { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(fmt, "Enable debug_assertions() for more info.") - } -} - -#[inline(always)] -fn b2b_g(v: &mut [u64; 16], - a: usize, - b: usize, - c: usize, - d: usize, - x: u64, - y: u64) -{ - v[a] = v[a].wrapping_add(v[b]).wrapping_add(x); - v[d] = (v[d] ^ v[a]).rotate_right(32); - v[c] = v[c].wrapping_add(v[d]); - v[b] = (v[b] ^ v[c]).rotate_right(24); - v[a] = v[a].wrapping_add(v[b]).wrapping_add(y); - v[d] = (v[d] ^ v[a]).rotate_right(16); - v[c] = v[c].wrapping_add(v[d]); - v[b] = (v[b] ^ v[c]).rotate_right(63); -} - -// Initialization vector -const BLAKE2B_IV: [u64; 8] = [ - 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B, - 0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1, - 0x510E527FADE682D1, 0x9B05688C2B3E6C1F, - 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179 -]; - -fn blake2b_compress(ctx: &mut Blake2bCtx, last: bool) { - - const SIGMA: [[usize; 16]; 12] = [ - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], - [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ], - [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 ], - [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 ], - [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 ], - [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 ], - [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 ], - [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 ], - [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 ], - [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 ], - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], - [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ] - ]; - - let mut v: [u64; 16] = [ - ctx.h[0], - ctx.h[1], - ctx.h[2], - ctx.h[3], - ctx.h[4], - ctx.h[5], - ctx.h[6], - ctx.h[7], - - BLAKE2B_IV[0], - BLAKE2B_IV[1], - BLAKE2B_IV[2], - BLAKE2B_IV[3], - BLAKE2B_IV[4], - BLAKE2B_IV[5], - BLAKE2B_IV[6], - BLAKE2B_IV[7], - ]; - - v[12] ^= ctx.t[0]; // low 64 bits of offset - v[13] ^= ctx.t[1]; // high 64 bits - if last { - v[14] = !v[14]; - } - - { - // Re-interpret the input buffer in the state as an array - // of little-endian u64s, converting them to machine - // endianness. It's OK to modify the buffer in place - // since this is the last time this data will be accessed - // before it's overwritten. - - let m: &mut [u64; 16] = unsafe { - let b: &mut [u8; 128] = &mut ctx.b; - ::std::mem::transmute(b) - }; - - if cfg!(target_endian = "big") { - for word in &mut m[..] { - *word = u64::from_le(*word); - } - } - - for i in 0 .. 12 { - b2b_g(&mut v, 0, 4, 8, 12, m[SIGMA[i][ 0]], m[SIGMA[i][ 1]]); - b2b_g(&mut v, 1, 5, 9, 13, m[SIGMA[i][ 2]], m[SIGMA[i][ 3]]); - b2b_g(&mut v, 2, 6, 10, 14, m[SIGMA[i][ 4]], m[SIGMA[i][ 5]]); - b2b_g(&mut v, 3, 7, 11, 15, m[SIGMA[i][ 6]], m[SIGMA[i][ 7]]); - b2b_g(&mut v, 0, 5, 10, 15, m[SIGMA[i][ 8]], m[SIGMA[i][ 9]]); - b2b_g(&mut v, 1, 6, 11, 12, m[SIGMA[i][10]], m[SIGMA[i][11]]); - b2b_g(&mut v, 2, 7, 8, 13, m[SIGMA[i][12]], m[SIGMA[i][13]]); - b2b_g(&mut v, 3, 4, 9, 14, m[SIGMA[i][14]], m[SIGMA[i][15]]); - } - } - - for i in 0 .. 8 { - ctx.h[i] ^= v[i] ^ v[i + 8]; - } -} - -fn blake2b_new(outlen: usize, key: &[u8]) -> Blake2bCtx { - assert!(outlen > 0 && outlen <= 64 && key.len() <= 64); - - let mut ctx = Blake2bCtx { - b: [0; 128], - h: BLAKE2B_IV, - t: [0; 2], - c: 0, - outlen: outlen as u16, - finalized: false, - - #[cfg(debug_assertions)] - fnv_hash: 0xcbf29ce484222325, - }; - - ctx.h[0] ^= 0x01010000 ^ ((key.len() << 8) as u64) ^ (outlen as u64); - - if key.len() > 0 { - blake2b_update(&mut ctx, key); - ctx.c = ctx.b.len(); - } - - ctx -} - -fn blake2b_update(ctx: &mut Blake2bCtx, mut data: &[u8]) { - assert!(!ctx.finalized, "Blake2bCtx already finalized"); - - let mut bytes_to_copy = data.len(); - let mut space_in_buffer = ctx.b.len() - ctx.c; - - while bytes_to_copy > space_in_buffer { - checked_mem_copy(data, &mut ctx.b[ctx.c .. ], space_in_buffer); - - ctx.t[0] = ctx.t[0].wrapping_add(ctx.b.len() as u64); - if ctx.t[0] < (ctx.b.len() as u64) { - ctx.t[1] += 1; - } - blake2b_compress(ctx, false); - ctx.c = 0; - - data = &data[space_in_buffer .. ]; - bytes_to_copy -= space_in_buffer; - space_in_buffer = ctx.b.len(); - } - - if bytes_to_copy > 0 { - checked_mem_copy(data, &mut ctx.b[ctx.c .. ], bytes_to_copy); - ctx.c += bytes_to_copy; - } - - #[cfg(debug_assertions)] - { - // compute additional FNV hash for simpler to read debug output - const MAGIC_PRIME: u64 = 0x00000100000001b3; - - for &byte in data { - ctx.fnv_hash = (ctx.fnv_hash ^ byte as u64).wrapping_mul(MAGIC_PRIME); - } - } -} - -fn blake2b_final(ctx: &mut Blake2bCtx) -{ - assert!(!ctx.finalized, "Blake2bCtx already finalized"); - - ctx.t[0] = ctx.t[0].wrapping_add(ctx.c as u64); - if ctx.t[0] < ctx.c as u64 { - ctx.t[1] += 1; - } - - while ctx.c < 128 { - ctx.b[ctx.c] = 0; - ctx.c += 1; - } - - blake2b_compress(ctx, true); - - // Modify our buffer to little-endian format as it will be read - // as a byte array. It's OK to modify the buffer in place since - // this is the last time this data will be accessed. - if cfg!(target_endian = "big") { - for word in &mut ctx.h { - *word = word.to_le(); - } - } - - ctx.finalized = true; -} - -#[inline(always)] -fn checked_mem_copy(from: &[T1], to: &mut [T2], byte_count: usize) { - let from_size = from.len() * mem::size_of::(); - let to_size = to.len() * mem::size_of::(); - assert!(from_size >= byte_count); - assert!(to_size >= byte_count); - let from_byte_ptr = from.as_ptr() as * const u8; - let to_byte_ptr = to.as_mut_ptr() as * mut u8; - unsafe { - ::std::ptr::copy_nonoverlapping(from_byte_ptr, to_byte_ptr, byte_count); - } -} - -pub fn blake2b(out: &mut [u8], key: &[u8], data: &[u8]) -{ - let mut ctx = blake2b_new(out.len(), key); - blake2b_update(&mut ctx, data); - blake2b_final(&mut ctx); - checked_mem_copy(&ctx.h, out, ctx.outlen as usize); -} - -pub struct Blake2bHasher(Blake2bCtx); - -impl ::std::hash::Hasher for Blake2bHasher { - fn write(&mut self, bytes: &[u8]) { - blake2b_update(&mut self.0, bytes); - } - - fn finish(&self) -> u64 { - assert!(self.0.outlen == 8, - "Hasher initialized with incompatible output length"); - u64::from_le(self.0.h[0]) - } -} - -impl Blake2bHasher { - pub fn new(outlen: usize, key: &[u8]) -> Blake2bHasher { - Blake2bHasher(blake2b_new(outlen, key)) - } - - pub fn finalize(&mut self) -> &[u8] { - if !self.0.finalized { - blake2b_final(&mut self.0); - } - debug_assert!(mem::size_of_val(&self.0.h) >= self.0.outlen as usize); - let raw_ptr = (&self.0.h[..]).as_ptr() as * const u8; - unsafe { - slice::from_raw_parts(raw_ptr, self.0.outlen as usize) - } - } -} - -impl ::std::fmt::Debug for Blake2bHasher { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - write!(fmt, "{:?}", self.0) - } -} - -#[cfg(test)] -fn selftest_seq(out: &mut [u8], seed: u32) -{ - let mut a: u32 = 0xDEAD4BADu32.wrapping_mul(seed); - let mut b: u32 = 1; - - for i in 0 .. out.len() { - let t: u32 = a.wrapping_add(b); - a = b; - b = t; - out[i] = ((t >> 24) & 0xFF) as u8; - } -} - -#[test] -fn blake2b_selftest() -{ - use std::hash::Hasher; - - // grand hash of hash results - const BLAKE2B_RES: [u8; 32] = [ - 0xC2, 0x3A, 0x78, 0x00, 0xD9, 0x81, 0x23, 0xBD, - 0x10, 0xF5, 0x06, 0xC6, 0x1E, 0x29, 0xDA, 0x56, - 0x03, 0xD7, 0x63, 0xB8, 0xBB, 0xAD, 0x2E, 0x73, - 0x7F, 0x5E, 0x76, 0x5A, 0x7B, 0xCC, 0xD4, 0x75 - ]; - - // parameter sets - const B2B_MD_LEN: [usize; 4] = [20, 32, 48, 64]; - const B2B_IN_LEN: [usize; 6] = [0, 3, 128, 129, 255, 1024]; - - let mut data = [0u8; 1024]; - let mut md = [0u8; 64]; - let mut key = [0u8; 64]; - - let mut hasher = Blake2bHasher::new(32, &[]); - - for i in 0 .. 4 { - let outlen = B2B_MD_LEN[i]; - for j in 0 .. 6 { - let inlen = B2B_IN_LEN[j]; - - selftest_seq(&mut data[.. inlen], inlen as u32); // unkeyed hash - blake2b(&mut md[.. outlen], &[], &data[.. inlen]); - hasher.write(&md[.. outlen]); // hash the hash - - selftest_seq(&mut key[0 .. outlen], outlen as u32); // keyed hash - blake2b(&mut md[.. outlen], &key[.. outlen], &data[.. inlen]); - hasher.write(&md[.. outlen]); // hash the hash - } - } - - // compute and compare the hash of hashes - let md = hasher.finalize(); - for i in 0 .. 32 { - assert_eq!(md[i], BLAKE2B_RES[i]); - } -} diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index a35ef2f7ce7..33d760d0a14 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -57,7 +57,6 @@ pub mod small_vec; pub mod base_n; pub mod bitslice; pub mod bitvec; -pub mod blake2b; pub mod graph; pub mod indexed_set; pub mod indexed_vec; @@ -70,7 +69,6 @@ pub mod transitive_relation; pub mod unify; pub mod fx; pub mod tuple_slice; -pub mod veccell; pub mod control_flow_graph; pub mod flock; pub mod sync; diff --git a/src/librustc_data_structures/veccell/mod.rs b/src/librustc_data_structures/veccell/mod.rs deleted file mode 100644 index 054eee8829a..00000000000 --- a/src/librustc_data_structures/veccell/mod.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cell::UnsafeCell; -use std::mem; - -pub struct VecCell { - data: UnsafeCell>, -} - -impl VecCell { - pub fn with_capacity(capacity: usize) -> VecCell { - VecCell { data: UnsafeCell::new(Vec::with_capacity(capacity)) } - } - - #[inline] - pub fn push(&self, data: T) -> usize { - // The logic here, and in `swap` below, is that the `push` - // method on the vector will not recursively access this - // `VecCell`. Therefore, we can temporarily obtain mutable - // access, secure in the knowledge that even if aliases exist - // -- indeed, even if aliases are reachable from within the - // vector -- they will not be used for the duration of this - // particular fn call. (Note that we also are relying on the - // fact that `VecCell` is not `Sync`.) - unsafe { - let v = self.data.get(); - (*v).push(data); - (*v).len() - } - } - - pub fn swap(&self, mut data: Vec) -> Vec { - unsafe { - let v = self.data.get(); - mem::swap(&mut *v, &mut data); - } - data - } -} diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 50c19b5a99a..f344624666a 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -170,6 +170,13 @@ pub fn compile_input(trans: Box, return Ok(()) } + if let &Some(ref dir) = outdir { + if fs::create_dir_all(dir).is_err() { + sess.err("failed to find or create the directory specified by --out-dir"); + return Err(CompileIncomplete::Stopped); + } + } + let arenas = AllArenas::new(); // Construct the HIR map diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 02fcb69fef5..52b87282180 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -716,6 +716,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { ReifyFnPointer => { match self.eval_operand(operand)?.ty.sty { ty::TyFnDef(def_id, substs) => { + if self.tcx.has_attr(def_id, "rustc_args_required_const") { + bug!("reifying a fn ptr that requires \ + const arguments"); + } let instance = self.resolve(def_id, substs)?; let fn_ptr = self.memory.create_fn_alloc(instance); let valty = ValTy { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 95a507ab9e3..8cb25f449b6 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -1026,9 +1026,14 @@ fn import_path_to_string(names: &[SpannedIdent], if names.is_empty() { import_directive_subclass_to_string(subclass) } else { - let x = format!("{}::{}", - names_to_string(names), - import_directive_subclass_to_string(subclass)); + // Note that this code looks a little wonky, it's currently here to + // hopefully help debug #48116, but otherwise isn't intended to + // cause any problems. + let x = format!( + "{}::{}", + names_to_string(names), + import_directive_subclass_to_string(subclass), + ); assert!(!names.is_empty()); assert!(!x.starts_with("::")); return x diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 49b4ef0d385..d470f92b752 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -714,6 +714,10 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { mir::CastKind::ReifyFnPointer => { match operand.ty.sty { ty::TyFnDef(def_id, substs) => { + if tcx.has_attr(def_id, "rustc_args_required_const") { + bug!("reifying a fn ptr that requires \ + const arguments"); + } callee::resolve_and_get_fn(self.cx, def_id, substs) } _ => { diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index d1bc4fe9001..2e876ec118d 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -195,6 +195,10 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { mir::CastKind::ReifyFnPointer => { match operand.layout.ty.sty { ty::TyFnDef(def_id, substs) => { + if bx.cx.tcx.has_attr(def_id, "rustc_args_required_const") { + bug!("reifying a fn ptr that requires \ + const arguments"); + } OperandValue::Immediate( callee::resolve_and_get_fn(bx.cx, def_id, substs)) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5fd4e0cb109..165b499cc62 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4897,6 +4897,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } + self.check_rustc_args_require_const(def.def_id(), node_id, span); + debug!("instantiate_value_path: type of {:?} is {:?}", node_id, ty_substituted); @@ -4904,6 +4906,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty_substituted } + fn check_rustc_args_require_const(&self, + def_id: DefId, + node_id: ast::NodeId, + span: Span) { + // We're only interested in functions tagged with + // #[rustc_args_required_const], so ignore anything that's not. + if !self.tcx.has_attr(def_id, "rustc_args_required_const") { + return + } + + // If our calling expression is indeed the function itself, we're good! + // If not, generate an error that this can only be called directly. + match self.tcx.hir.get(self.tcx.hir.get_parent_node(node_id)) { + Node::NodeExpr(expr) => { + match expr.node { + hir::ExprCall(ref callee, ..) => { + if callee.id == node_id { + return + } + } + _ => {} + } + } + _ => {} + } + + self.tcx.sess.span_err(span, "this function can only be invoked \ + directly, not through a function pointer"); + } + /// Report errors if the provided parameters are too few or too many. fn check_path_parameter_count(&self, span: Span, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7c9a49c82a9..66b5f3b5ea3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1051,6 +1051,10 @@ impl Clean for [ast::Attribute] { if UnstableFeatures::from_environment().is_nightly_build() { let dox = attrs.collapsed_doc_value().unwrap_or_else(String::new); for link in markdown_links(&dox, cx.render_type) { + // bail early for real links + if link.contains('/') { + continue; + } let (def, fragment) = { let mut kind = PathKind::Unknown; let path_str = if let Some(prefix) = diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 63ebb16e5e0..0eb4f9ba7e5 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -106,7 +106,9 @@ pub fn where_clauses(cx: &DocContext, clauses: Vec) -> Vec { } PP::Parenthesized { ref mut output, .. } => { assert!(output.is_none()); - *output = Some(rhs.clone()); + if *rhs != clean::Type::Tuple(Vec::new()) { + *output = Some(rhs.clone()); + } } }; true diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index ba9bcb7af7a..f688be89bee 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -123,25 +123,9 @@ sidebar.appendChild(div); } } - var themeChoices = document.getElementById("theme-choices"); - if (themeChoices) { - if (!themesWidth) { - var savedState = themeChoices.style.display; - themeChoices.style.display = 'block'; - themesWidth = themeChoices.offsetWidth + 'px'; - themeChoices.style.display = savedState; - } - themeChoices.style.position = "fixed"; - themeChoices.style.width = themesWidth; - themeChoices.style.top = '78px'; - themeChoices.style.left = '250px'; - } - document.getElementsByTagName("body")[0].style.marginTop = '45px'; - var themePicker = document.getElementById("theme-picker"); - if (themePicker) { - themePicker.style.position = "fixed"; - themePicker.style.top = "50px"; - themePicker.style.left = "250px"; + var themePicker = document.getElementsByClassName("theme-picker"); + if (themePicker && themePicker.length > 0) { + themePicker[0].style.display = "none"; } } @@ -157,18 +141,9 @@ filler.remove(); } document.getElementsByTagName("body")[0].style.marginTop = ''; - var themePicker = document.getElementById("theme-picker"); - if (themePicker) { - themePicker.style.position = "absolute"; - themePicker.style.top = null; - themePicker.style.left = null; - } - var themeChoices = document.getElementById("theme-choices"); - if (themeChoices) { - themeChoices.style.position = 'absolute'; - themeChoices.style.width = null; - themeChoices.style.top = null; - themeChoices.style.left = null; + var themePicker = document.getElementsByClassName("theme-picker"); + if (themePicker && themePicker.length > 0) { + themePicker[0].style.display = null; } } diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 53d57b67230..cd4f2cfa678 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -899,7 +899,7 @@ span.since { } #main { - margin-top: 50px; + margin-top: 45px; padding: 0; } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9c6520cd874..ae0556320b0 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -984,6 +984,11 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG "wasm_import_memory attribute is currently unstable", cfg_fn!(wasm_import_memory))), + ("rustc_args_required_const", Whitelisted, Gated(Stability::Unstable, + "rustc_attrs", + "never will be stable", + cfg_fn!(rustc_attrs))), + // Crate level attributes ("crate_name", CrateLevel, Ungated), ("crate_type", CrateLevel, Ungated), diff --git a/src/test/compile-fail/rustc-args-required-const2.rs b/src/test/compile-fail/rustc-args-required-const2.rs new file mode 100644 index 00000000000..aa63019307b --- /dev/null +++ b/src/test/compile-fail/rustc-args-required-const2.rs @@ -0,0 +1,20 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(attr_literals, rustc_attrs, const_fn)] + +#[rustc_args_required_const(0)] +fn foo(_a: i32) { +} + +fn main() { + let a = foo; //~ ERROR: this function can only be invoked directly + a(2); +} diff --git a/src/test/rustdoc/auxiliary/unit-return.rs b/src/test/rustdoc/auxiliary/unit-return.rs new file mode 100644 index 00000000000..1b30a6a4328 --- /dev/null +++ b/src/test/rustdoc/auxiliary/unit-return.rs @@ -0,0 +1,13 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn f2(f: F) {} + +pub fn f3 () + Clone>(f: F) {} diff --git a/src/test/rustdoc/unit-return.rs b/src/test/rustdoc/unit-return.rs new file mode 100644 index 00000000000..757e8979edd --- /dev/null +++ b/src/test/rustdoc/unit-return.rs @@ -0,0 +1,27 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:unit-return.rs + +#![crate_name = "foo"] + +extern crate unit_return; + +// @has 'foo/fn.f0.html' '//*[@class="rust fn"]' 'F: FnMut(u8) + Clone' +pub fn f0(f: F) {} + +// @has 'foo/fn.f1.html' '//*[@class="rust fn"]' 'F: FnMut(u16) + Clone' +pub fn f1 () + Clone>(f: F) {} + +// @has 'foo/fn.f2.html' '//*[@class="rust fn"]' 'F: FnMut(u32) + Clone' +pub use unit_return::f2; + +// @has 'foo/fn.f3.html' '//*[@class="rust fn"]' 'F: FnMut(u64) + Clone' +pub use unit_return::f3; diff --git a/src/test/ui/generator/issue-48048.rs b/src/test/ui/generator/issue-48048.rs new file mode 100644 index 00000000000..89739bd591c --- /dev/null +++ b/src/test/ui/generator/issue-48048.rs @@ -0,0 +1,23 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(generators)] + +fn main() { + let x = (|_| {},); + + || { + let x = x; + + x.0({ //~ ERROR borrow may still be in use when generator yields + yield; + }); + }; +} diff --git a/src/test/ui/generator/issue-48048.stderr b/src/test/ui/generator/issue-48048.stderr new file mode 100644 index 00000000000..fd1667128ab --- /dev/null +++ b/src/test/ui/generator/issue-48048.stderr @@ -0,0 +1,10 @@ +error[E0626]: borrow may still be in use when generator yields + --> $DIR/issue-48048.rs:19:9 + | +19 | x.0({ //~ ERROR borrow may still be in use when generator yields + | ^^^ +20 | yield; + | ----- possible yield occurs here + +error: aborting due to previous error + diff --git a/src/test/ui/mismatched_types/binops.rs b/src/test/ui/mismatched_types/binops.rs index 5144b59955c..3f2cb59b11d 100644 --- a/src/test/ui/mismatched_types/binops.rs +++ b/src/test/ui/mismatched_types/binops.rs @@ -10,7 +10,7 @@ fn main() { 1 + Some(1); //~ ERROR cannot add `std::option::Option<{integer}>` to `{integer}` - 2 as usize - Some(1); //~ ERROR cannot substract `std::option::Option<{integer}>` from `usize` + 2 as usize - Some(1); //~ ERROR cannot subtract `std::option::Option<{integer}>` from `usize` 3 * (); //~ ERROR cannot multiply `()` to `{integer}` 4 / ""; //~ ERROR cannot divide `{integer}` by `&str` 5 < String::new(); //~ ERROR is not satisfied diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index 1b7fba05063..828cf636951 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr @@ -6,10 +6,10 @@ error[E0277]: cannot add `std::option::Option<{integer}>` to `{integer}` | = help: the trait `std::ops::Add>` is not implemented for `{integer}` -error[E0277]: cannot substract `std::option::Option<{integer}>` from `usize` +error[E0277]: cannot subtract `std::option::Option<{integer}>` from `usize` --> $DIR/binops.rs:13:16 | -13 | 2 as usize - Some(1); //~ ERROR cannot substract `std::option::Option<{integer}>` from `usize` +13 | 2 as usize - Some(1); //~ ERROR cannot subtract `std::option::Option<{integer}>` from `usize` | ^ no implementation for `usize - std::option::Option<{integer}>` | = help: the trait `std::ops::Sub>` is not implemented for `usize` diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs index 96e5201716c..34232e81cbd 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.rs +++ b/src/test/ui/mismatched_types/closure-arg-count.rs @@ -36,6 +36,9 @@ fn main() { //~^ ERROR closure is expected to take let _it = vec![1, 2, 3].into_iter().enumerate().map(qux); //~^ ERROR function is expected to take + + let _it = vec![1, 2, 3].into_iter().map(usize::checked_add); + //~^ ERROR function is expected to take } fn foo() {} diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index be00ee4d74e..d2a6d6da814 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -90,7 +90,7 @@ error[E0593]: function is expected to take a single 2-tuple as argument, but it 32 | let _it = vec![1, 2, 3].into_iter().enumerate().map(foo); | ^^^ expected function that takes a single 2-tuple as argument ... -41 | fn foo() {} +44 | fn foo() {} | -------- takes 0 arguments error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments @@ -107,8 +107,14 @@ error[E0593]: function is expected to take a single 2-tuple as argument, but it 37 | let _it = vec![1, 2, 3].into_iter().enumerate().map(qux); | ^^^ expected function that takes a single 2-tuple as argument ... -42 | fn qux(x: usize, y: usize) {} +45 | fn qux(x: usize, y: usize) {} | -------------------------- takes 2 distinct arguments -error: aborting due to 11 previous errors +error[E0593]: function is expected to take 1 argument, but it takes 2 arguments + --> $DIR/closure-arg-count.rs:40:41 + | +40 | let _it = vec![1, 2, 3].into_iter().map(usize::checked_add); + | ^^^ expected function that takes 1 argument + +error: aborting due to 12 previous errors