Auto merge of #48113 - kennytm:rollup, r=kennytm
Rollup of 20 pull requests - Successful merges: #47790, #47835, #47854, #48015, #48047, #48051, #48058, #48059, #48064, #48078, #48080, #48086, #48098, #48101, #48107, #48100, #48085, #48120, #48124, #47547 - Failed merges:
This commit is contained in:
commit
45fba43b3d
@ -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
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 1c9bf65aa0e371b84755a8ddd6e79497fac57171
|
||||
Subproject commit 17841e155edf858c8ea7802dd5f5ecbef54b989f
|
@ -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);
|
||||
}
|
||||
|
@ -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<Interned<String>, Target>,
|
||||
pub full_bootstrap: bool,
|
||||
pub extended: bool,
|
||||
pub tools: Option<HashSet<String>>,
|
||||
pub sanitizers: bool,
|
||||
pub profiler: bool,
|
||||
pub ignore_git: bool,
|
||||
@ -191,6 +192,7 @@ struct Build {
|
||||
python: Option<String>,
|
||||
full_bootstrap: Option<bool>,
|
||||
extended: Option<bool>,
|
||||
tools: Option<HashSet<String>>,
|
||||
verbose: Option<usize>,
|
||||
sanitizers: Option<bool>,
|
||||
profiler: Option<bool>,
|
||||
@ -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);
|
||||
|
@ -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")
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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<String>) {
|
||||
install_sh(builder, "docs", "rust-docs", stage, Some(host));
|
||||
@ -144,6 +145,19 @@ macro_rules! install {
|
||||
pub host: Interned<String>,
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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<String>) -> Option<&Path> {
|
||||
if let Some(linker) = self.config.target_config.get(&target)
|
||||
.and_then(|c| c.linker.as_ref()) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit a2b424b600235af58f453577c2da1b0e1de2ffa5
|
||||
Subproject commit 9b2dcac06c3e23235f8997b3c5f2325a6d3382df
|
@ -1 +1 @@
|
||||
Subproject commit a645960fe48946153936dd5628df4a90bd837981
|
||||
Subproject commit ec5660820dea91df470dab0b9eb26ef798f20889
|
@ -1 +1 @@
|
||||
Subproject commit fec3182d0b0a3cf8122e192b3270064a5b19be5b
|
||||
Subproject commit ad5ddd62c098d5b424151beda574ae7df2154df1
|
@ -1 +1 @@
|
||||
Subproject commit e6a5d5d10aa2fde0baed7b29bf672bd9f3af8962
|
||||
Subproject commit 254df654a9b75abf6ca08806535dbe1fad41be3f
|
@ -1 +1 @@
|
||||
Subproject commit 4ebb8169dfe569b3dcbeab560607800bb717978a
|
||||
Subproject commit 919980be7df4ea7d45a9dca8efc34da89bcf7d6b
|
@ -18,7 +18,7 @@
|
||||
<!-- Upgrade code should be different for each platform -->
|
||||
<?if $(sys.BUILDARCH)="x64" ?>
|
||||
<?if $(env.CFG_ABI)="GNU" ?>
|
||||
<!-- UpgradeCode shoud stay the same for all MSI versions in channel -->
|
||||
<!-- UpgradeCode should stay the same for all MSI versions in channel -->
|
||||
<?if $(env.CFG_CHANNEL)="stable" ?>
|
||||
<?define UpgradeCode="B440B077-F8D1-4730-8E1D-D6D37702B4CE" ?>
|
||||
<?elseif $(env.CFG_CHANNEL)="beta" ?>
|
||||
@ -129,7 +129,7 @@
|
||||
|
||||
<!-- Path of cmd.exe for the shortcut -->
|
||||
<Property Id="SHORTCUTTARGET" Value="%windir%\System32\cmd.exe" />
|
||||
<!-- Microsoft Installer will resolve any Enviroment Variables in the working directory at install time -->
|
||||
<!-- Microsoft Installer will resolve any Environment Variables in the working directory at install time -->
|
||||
<Property Id="SHORTCUTWKDIR" Value="%SystemDrive%\" />
|
||||
|
||||
<InstallUISequence>
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -211,7 +211,7 @@ impl From<u8> 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,
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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")]
|
||||
|
||||
|
@ -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.")?;
|
||||
|
@ -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<RHS=Self> {
|
||||
/// 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<Rhs=Self> {
|
||||
/// Performs the `-=` operation.
|
||||
|
@ -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<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn atomic_nand<T>(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<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
||||
match order {
|
||||
|
@ -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);
|
||||
|
@ -42,6 +42,7 @@
|
||||
#![feature(try_from)]
|
||||
#![feature(try_trait)]
|
||||
#![feature(exact_chunks)]
|
||||
#![feature(atomic_nand)]
|
||||
|
||||
extern crate core;
|
||||
extern crate test;
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -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<Span>,
|
||||
expected_args: Vec<ArgKind>,
|
||||
found_args: Vec<ArgKind>,
|
||||
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::<Vec<String>>().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::<Vec<String>>().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::<Vec<String>>()
|
||||
.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::<Vec<String>>()
|
||||
.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::<Vec<String>>()
|
||||
.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::<Vec<String>>()
|
||||
.join(", "))
|
||||
} else {
|
||||
"".to_owned()
|
||||
},
|
||||
);
|
||||
err.span_suggestion(found_span,
|
||||
"change the closure to accept a tuple instead of \
|
||||
individual arguments",
|
||||
sugg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 <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.
|
||||
|
||||
|
||||
// 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<T1, T2>(from: &[T1], to: &mut [T2], byte_count: usize) {
|
||||
let from_size = from.len() * mem::size_of::<T1>();
|
||||
let to_size = to.len() * mem::size_of::<T2>();
|
||||
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]);
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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 <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::cell::UnsafeCell;
|
||||
use std::mem;
|
||||
|
||||
pub struct VecCell<T> {
|
||||
data: UnsafeCell<Vec<T>>,
|
||||
}
|
||||
|
||||
impl<T> VecCell<T> {
|
||||
pub fn with_capacity(capacity: usize) -> VecCell<T> {
|
||||
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<T>) -> Vec<T> {
|
||||
unsafe {
|
||||
let v = self.data.get();
|
||||
mem::swap(&mut *v, &mut data);
|
||||
}
|
||||
data
|
||||
}
|
||||
}
|
@ -170,6 +170,13 @@ pub fn compile_input(trans: Box<TransCrate>,
|
||||
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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
_ => {
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -1051,6 +1051,10 @@ impl Clean<Attributes> 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) =
|
||||
|
@ -106,7 +106,9 @@ pub fn where_clauses(cx: &DocContext, clauses: Vec<WP>) -> Vec<WP> {
|
||||
}
|
||||
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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -899,7 +899,7 @@ span.since {
|
||||
}
|
||||
|
||||
#main {
|
||||
margin-top: 50px;
|
||||
margin-top: 45px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
20
src/test/compile-fail/rustc-args-required-const2.rs
Normal file
20
src/test/compile-fail/rustc-args-required-const2.rs
Normal file
@ -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 <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(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);
|
||||
}
|
13
src/test/rustdoc/auxiliary/unit-return.rs
Normal file
13
src/test/rustdoc/auxiliary/unit-return.rs
Normal file
@ -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 <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 f2<F: FnMut(u32) + Clone>(f: F) {}
|
||||
|
||||
pub fn f3<F: FnMut(u64) -> () + Clone>(f: F) {}
|
27
src/test/rustdoc/unit-return.rs
Normal file
27
src/test/rustdoc/unit-return.rs
Normal file
@ -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 <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: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: FnMut(u8) + Clone>(f: F) {}
|
||||
|
||||
// @has 'foo/fn.f1.html' '//*[@class="rust fn"]' 'F: FnMut(u16) + Clone'
|
||||
pub fn f1<F: FnMut(u16) -> () + 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;
|
23
src/test/ui/generator/issue-48048.rs
Normal file
23
src/test/ui/generator/issue-48048.rs
Normal file
@ -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 <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(generators)]
|
||||
|
||||
fn main() {
|
||||
let x = (|_| {},);
|
||||
|
||||
|| {
|
||||
let x = x;
|
||||
|
||||
x.0({ //~ ERROR borrow may still be in use when generator yields
|
||||
yield;
|
||||
});
|
||||
};
|
||||
}
|
10
src/test/ui/generator/issue-48048.stderr
Normal file
10
src/test/ui/generator/issue-48048.stderr
Normal file
@ -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
|
||||
|
@ -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
|
||||
|
@ -6,10 +6,10 @@ error[E0277]: cannot add `std::option::Option<{integer}>` to `{integer}`
|
||||
|
|
||||
= help: the trait `std::ops::Add<std::option::Option<{integer}>>` 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<std::option::Option<{integer}>>` is not implemented for `usize`
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user