diff --git a/config.toml.example b/config.toml.example index c2ec731eeb8a2..f153562a53894 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 1c9bf65aa0e37..17841e155edf8 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 6c68ee18506bb..9403c343d1d9d 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -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 be8910120ee19..4f4fd14ae8cab 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 d51752a12d9e5..99a3ee4e4c369 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -144,6 +144,7 @@ def v(*args): 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 6717b1cb09883..460fb016f16ea 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 743f32ece99c6..20f7d379a6967 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/native.rs b/src/bootstrap/native.rs index 3f30756a568ce..6d669584d2d56 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -186,7 +186,7 @@ impl Step for Llvm { } // http://llvm.org/docs/HowToCrossCompileLLVM.html - if target != build.build { + if target != build.build && !self.emscripten { builder.ensure(Llvm { target: build.build, emscripten: false, diff --git a/src/ci/docker/dist-i686-linux/Dockerfile b/src/ci/docker/dist-i686-linux/Dockerfile index 0fd6af6e10d34..5e405aa72e83d 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/dlmalloc b/src/dlmalloc index d3812c3accaee..8c3141db4f8ef 160000 --- a/src/dlmalloc +++ b/src/dlmalloc @@ -1 +1 @@ -Subproject commit d3812c3accaee7ad23068ed4fc089cc05c7a538f +Subproject commit 8c3141db4f8ef2fb0154740c87d6970ec7752d74 diff --git a/src/doc/book b/src/doc/book index a645960fe4894..ec5660820dea9 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 fec3182d0b0a3..ad5ddd62c098d 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 e6a5d5d10aa2f..254df654a9b75 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 4ebb8169dfe56..919980be7df4e 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/libcore/char.rs b/src/libcore/char.rs index e8b81db07067c..7215bd2a47684 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/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 97cf9b01410b1..b804cf7bf5a34 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 d4bcf00be8089..a290839425ebe 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 6b8bf8df0d33f..0000000000000 --- 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 a35ef2f7ce7ba..33d760d0a1482 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 054eee8829a4a..0000000000000 --- 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 50c19b5a99a54..f344624666a6c 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 02fcb69fef5ac..52b87282180c4 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_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 49b4ef0d38549..d470f92b75231 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 d1bc4fe90014c..2e876ec118d57 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 5fd4e0cb109cc..165b499cc62aa 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 7c9a49c82a939..66b5f3b5ea366 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 63ebb16e5e009..0eb4f9ba7e581 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 ba9bcb7af7ae0..f688be89beebc 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 53d57b672303e..cd4f2cfa678e6 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 9c6520cd874a8..ae0556320b0ef 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 0000000000000..aa63019307b5b --- /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/run-pass/backtrace-debuginfo.rs b/src/test/run-pass/backtrace-debuginfo.rs index e8b5f3490e50e..2b82a8943636e 100644 --- a/src/test/run-pass/backtrace-debuginfo.rs +++ b/src/test/run-pass/backtrace-debuginfo.rs @@ -15,11 +15,14 @@ // Unfortunately, LLVM has no "disable" option for this, so we have to set // "enable" to 0 instead. -// compile-flags:-g -Cllvm-args=-enable-tail-merge=0 +// compile-flags:-g -Cllvm-args=-enable-tail-merge=0 -Cllvm-args=-opt-bisect-limit=0 // ignore-pretty issue #37195 // ignore-cloudabi spawning processes is not supported // ignore-emscripten spawning processes is not supported +// note that above `-opt-bisect-limit=0` is used to basically disable +// optimizations + use std::env; #[path = "backtrace-debuginfo-aux.rs"] mod aux; @@ -114,18 +117,26 @@ fn outer(mut counter: i32, main_pos: Pos) { inner_inlined(&mut counter, main_pos, pos!()); } -fn check_trace(output: &str, error: &str) { +fn check_trace(output: &str, error: &str) -> Result<(), String> { // reverse the position list so we can start with the last item (which was the first line) let mut remaining: Vec<&str> = output.lines().map(|s| s.trim()).rev().collect(); - assert!(error.contains("stack backtrace"), "no backtrace in the error: {}", error); + if !error.contains("stack backtrace") { + return Err(format!("no backtrace found in stderr:\n{}", error)) + } for line in error.lines() { if !remaining.is_empty() && line.contains(remaining.last().unwrap()) { remaining.pop(); } } - assert!(remaining.is_empty(), - "trace does not match position list: {}\n---\n{}", error, output); + if !remaining.is_empty() { + return Err(format!("trace does not match position list\n\ + still need to find {:?}\n\n\ + --- stdout\n{}\n\ + --- stderr\n{}", + remaining, output, error)) + } + Ok(()) } fn run_test(me: &str) { @@ -133,6 +144,7 @@ fn run_test(me: &str) { use std::process::Command; let mut i = 0; + let mut errors = Vec::new(); loop { let out = Command::new(me) .env("RUST_BACKTRACE", "full") @@ -143,10 +155,20 @@ fn run_test(me: &str) { assert!(output.contains("done."), "bad output for successful run: {}", output); break; } else { - check_trace(output, error); + if let Err(e) = check_trace(output, error) { + errors.push(e); + } } i += 1; } + if errors.len() > 0 { + for error in errors { + println!("---------------------------------------"); + println!("{}", error); + } + + panic!("found some errors"); + } } #[inline(never)] diff --git a/src/test/rustdoc/auxiliary/unit-return.rs b/src/test/rustdoc/auxiliary/unit-return.rs new file mode 100644 index 0000000000000..1b30a6a43282f --- /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 0000000000000..757e8979edd4f --- /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 0000000000000..89739bd591cc8 --- /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 0000000000000..fd1667128ab60 --- /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/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs index 96e5201716c71..34232e81cbdee 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 be00ee4d74e7e..d2a6d6da814ca 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