Auto merge of #47622 - GuillaumeGomez:rollup, r=GuillaumeGomez

Rollup of 10 pull requests

- Successful merges: #46938, #47193, #47508, #47510, #47532, #47535, #47559, #47568, #47573, #47578
- Failed merges:
This commit is contained in:
bors 2018-01-21 06:32:03 +00:00
commit 8d3e93beae
20 changed files with 388 additions and 201 deletions

View File

@ -301,12 +301,12 @@ It's absolutely fine to have multiple build directories with different
[pull-requests]: #pull-requests
Pull requests are the primary mechanism we use to change Rust. GitHub itself
has some [great documentation][pull-requests] on using the Pull Request feature.
has some [great documentation][about-pull-requests] on using the Pull Request feature.
We use the "fork and pull" model [described here][development-models], where
contributors push changes to their personal fork and create pull requests to
bring those changes into the source repository.
[pull-requests]: https://help.github.com/articles/about-pull-requests/
[about-pull-requests]: https://help.github.com/articles/about-pull-requests/
[development-models]: https://help.github.com/articles/about-collaborative-development-models/
Please make pull requests against the `master` branch.

View File

@ -28,6 +28,7 @@ Rust provides a number of book-length sets of documentation, collectively
nicknamed 'The Rust Bookshelf.'
* [The Rust Programming Language][book] teaches you how to program in Rust.
* [Rust By Example][rbe] teaches you how to program in Rust using editable examples.
* [The Cargo Book][cargo-book] is a guide to Cargo, Rust's build tool and dependency manager.
* [The Unstable Book][unstable-book] has documentation for unstable features.
* [The Rustonomicon][nomicon] is your guidebook to the dark arts of unsafe Rust.
@ -51,6 +52,7 @@ before this policy was put into place. That work is being tracked
[refchecklist]: https://github.com/rust-lang-nursery/reference/issues/9
[err]: error-index.html
[book]: book/index.html
[rbe]: rust-by-example/index.html
[nomicon]: nomicon/index.html
[unstable-book]: unstable-book/index.html
[rustdoc-book]: rustdoc/index.html

View File

@ -881,6 +881,35 @@ impl<T: Default> Option<T> {
}
}
impl<T, E> Option<Result<T, E>> {
/// Transposes an `Option` of a `Result` into a `Result` of an `Option`.
///
/// `None` will be mapped to `Ok(None)`.
/// `Some(Ok(_))` and `Some(Err(_))` will be mapped to `Ok(Some(_))` and `Err(_)`.
///
/// # Examples
///
/// ```
/// #![feature(transpose_result)]
///
/// #[derive(Debug, Eq, PartialEq)]
/// struct SomeErr;
///
/// let x: Result<Option<i32>, SomeErr> = Ok(Some(5));
/// let y: Option<Result<i32, SomeErr>> = Some(Ok(5));
/// assert_eq!(x, y.transpose());
/// ```
#[inline]
#[unstable(feature = "transpose_result", issue = "47338")]
pub fn transpose(self) -> Result<Option<T>, E> {
match self {
Some(Ok(x)) => Ok(Some(x)),
Some(Err(e)) => Err(e),
None => Ok(None),
}
}
}
// This is a separate function to reduce the code size of .expect() itself.
#[inline(never)]
#[cold]

View File

@ -909,6 +909,35 @@ impl<T: Default, E> Result<T, E> {
}
}
impl<T, E> Result<Option<T>, E> {
/// Transposes a `Result` of an `Option` into an `Option` of a `Result`.
///
/// `Ok(None)` will be mapped to `None`.
/// `Ok(Some(_))` and `Err(_)` will be mapped to `Some(Ok(_))` and `Some(Err(_))`.
///
/// # Examples
///
/// ```
/// #![feature(transpose_result)]
///
/// #[derive(Debug, Eq, PartialEq)]
/// struct SomeErr;
///
/// let x: Result<Option<i32>, SomeErr> = Ok(Some(5));
/// let y: Option<Result<i32, SomeErr>> = Some(Ok(5));
/// assert_eq!(x.transpose(), y);
/// ```
#[inline]
#[unstable(feature = "transpose_result", issue = "47338")]
pub fn transpose(self) -> Option<Result<T, E>> {
match self {
Ok(Some(x)) => Some(Ok(x)),
Ok(None) => None,
Err(e) => Some(Err(e)),
}
}
}
// This is a separate function to reduce the code size of the methods
#[inline(never)]
#[cold]

View File

@ -717,93 +717,40 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
self.tcx.hir.span_if_local(did)
}).map(|sp| self.tcx.sess.codemap().def_span(sp)); // the sp could be an fn def
let found_ty_count =
match found_trait_ref.skip_binder().substs.type_at(1).sty {
ty::TyTuple(ref tys, _) => tys.len(),
_ => 1,
};
let (expected_tys, expected_ty_count) =
match expected_trait_ref.skip_binder().substs.type_at(1).sty {
ty::TyTuple(ref tys, _) =>
(tys.iter().map(|t| &t.sty).collect(), tys.len()),
ref sty => (vec![sty], 1),
};
if found_ty_count == expected_ty_count {
let found = match found_trait_ref.skip_binder().substs.type_at(1).sty {
ty::TyTuple(ref tys, _) => tys.iter()
.map(|_| ArgKind::empty()).collect::<Vec<_>>(),
_ => vec![ArgKind::empty()],
};
let expected = match expected_trait_ref.skip_binder().substs.type_at(1).sty {
ty::TyTuple(ref tys, _) => tys.iter()
.map(|t| match t.sty {
ty::TypeVariants::TyTuple(ref tys, _) => ArgKind::Tuple(
span,
tys.iter()
.map(|ty| ("_".to_owned(), format!("{}", ty.sty)))
.collect::<Vec<_>>()
),
_ => ArgKind::Arg("_".to_owned(), format!("{}", t.sty)),
}).collect(),
ref sty => vec![ArgKind::Arg("_".to_owned(), format!("{}", sty))],
};
if found.len()== expected.len() {
self.report_closure_arg_mismatch(span,
found_span,
found_trait_ref,
expected_trait_ref)
} else {
let expected_tuple = if expected_ty_count == 1 {
expected_tys.first().and_then(|t| {
if let &&ty::TyTuple(ref tuptys, _) = t {
Some(tuptys.len())
} else {
None
}
})
} else {
None
};
// FIXME(#44150): Expand this to "N args expected but a N-tuple found."
// Type of the 1st expected argument is somehow provided as type of a
// found one in that case.
//
// ```
// [1i32, 2, 3].sort_by(|(a, b)| ..)
// // ^^^^^^^ --------
// // expected_trait_ref: std::ops::FnMut<(&i32, &i32)>
// // found_trait_ref: std::ops::FnMut<(&i32,)>
// ```
let (closure_span, closure_args) = found_did
let (closure_span, found) = found_did
.and_then(|did| self.tcx.hir.get_if_local(did))
.and_then(|node| {
if let hir::map::NodeExpr(
&hir::Expr {
node: hir::ExprClosure(_, ref decl, id, span, _),
..
}) = node
{
let ty_snips = decl.inputs.iter()
.map(|ty| {
self.tcx.sess.codemap().span_to_snippet(ty.span).ok()
.and_then(|snip| {
// filter out dummy spans
if snip == "," || snip == "|" {
None
} else {
Some(snip)
}
})
})
.collect::<Vec<Option<String>>>();
.map(|node| self.get_fn_like_arguments(node))
.unwrap_or((found_span.unwrap(), found));
let body = self.tcx.hir.body(id);
let pat_snips = body.arguments.iter()
.map(|arg|
self.tcx.sess.codemap().span_to_snippet(arg.pat.span).ok())
.collect::<Option<Vec<String>>>();
Some((span, pat_snips, ty_snips))
} else {
None
}
})
.map(|(span, pat, ty)| (Some(span), Some((pat, ty))))
.unwrap_or((None, None));
let closure_args = closure_args.and_then(|(pat, ty)| Some((pat?, ty)));
self.report_arg_count_mismatch(
span,
closure_span.or(found_span),
expected_ty_count,
expected_tuple,
found_ty_count,
closure_args,
found_trait_ty.is_closure()
)
self.report_arg_count_mismatch(span,
closure_span,
expected,
found,
found_trait_ty.is_closure())
}
}
@ -845,94 +792,135 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
}
fn get_fn_like_arguments(&self, node: hir::map::Node) -> (Span, Vec<ArgKind>) {
if let hir::map::NodeExpr(&hir::Expr {
node: hir::ExprClosure(_, ref _decl, id, span, _),
..
}) = node {
(self.tcx.sess.codemap().def_span(span), self.tcx.hir.body(id).arguments.iter()
.map(|arg| {
if let hir::Pat {
node: hir::PatKind::Tuple(args, _),
span,
..
} = arg.pat.clone().into_inner() {
ArgKind::Tuple(
span,
args.iter().map(|pat| {
let snippet = self.tcx.sess.codemap()
.span_to_snippet(pat.span).unwrap();
(snippet, "_".to_owned())
}).collect::<Vec<_>>(),
)
} else {
let name = self.tcx.sess.codemap().span_to_snippet(arg.pat.span).unwrap();
ArgKind::Arg(name, "_".to_owned())
}
})
.collect::<Vec<ArgKind>>())
} else if let hir::map::NodeItem(&hir::Item {
span,
node: hir::ItemFn(ref decl, ..),
..
}) = node {
(self.tcx.sess.codemap().def_span(span), decl.inputs.iter()
.map(|arg| match arg.clone().into_inner().node {
hir::TyTup(ref tys) => ArgKind::Tuple(
arg.span,
tys.iter()
.map(|_| ("_".to_owned(), "_".to_owned()))
.collect::<Vec<_>>(),
),
_ => ArgKind::Arg("_".to_owned(), "_".to_owned())
}).collect::<Vec<ArgKind>>())
} else {
panic!("non-FnLike node found: {:?}", node);
}
}
fn report_arg_count_mismatch(
&self,
span: Span,
found_span: Option<Span>,
expected: usize,
expected_tuple: Option<usize>,
found: usize,
closure_args: Option<(Vec<String>, Vec<Option<String>>)>,
is_closure: bool
found_span: Span,
expected_args: Vec<ArgKind>,
found_args: Vec<ArgKind>,
is_closure: bool,
) -> DiagnosticBuilder<'tcx> {
use std::borrow::Cow;
let kind = if is_closure { "closure" } else { "function" };
let args_str = |n, distinct| format!(
"{} {}argument{}",
n,
if distinct && n >= 2 { "distinct " } else { "" },
if n == 1 { "" } else { "s" },
);
let expected_str = if let Some(n) = expected_tuple {
assert!(expected == 1);
if closure_args.as_ref().map(|&(ref pats, _)| pats.len()) == Some(n) {
Cow::from("a single tuple as argument")
} else {
// be verbose when numbers differ
Cow::from(format!("a single {}-tuple as argument", n))
let args_str = |arguments: &Vec<ArgKind>, other: &Vec<ArgKind>| {
let arg_length = arguments.len();
let distinct = match &other[..] {
&[ArgKind::Tuple(..)] => true,
_ => false,
};
match (arg_length, arguments.get(0)) {
(1, Some(&ArgKind::Tuple(_, ref fields))) => {
format!("a single {}-tuple as argument", fields.len())
}
_ => format!("{} {}argument{}",
arg_length,
if distinct && arg_length > 1 { "distinct " } else { "" },
if arg_length == 1 { "" } else { "s" }),
}
} else {
Cow::from(args_str(expected, false))
};
let found_str = if expected_tuple.is_some() {
args_str(found, true)
} else {
args_str(found, false)
};
let expected_str = args_str(&expected_args, &found_args);
let found_str = args_str(&found_args, &expected_args);
let mut err = struct_span_err!(self.tcx.sess, span, E0593,
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0593,
"{} is expected to take {}, but it takes {}",
kind,
expected_str,
found_str,
);
err.span_label(
span,
format!(
"expected {} that takes {}",
kind,
expected_str,
)
);
err.span_label(span, format!( "expected {} that takes {}", kind, expected_str));
err.span_label(found_span, format!("takes {}", found_str));
if let Some(span) = found_span {
if let (Some(expected_tuple), Some((pats, tys))) = (expected_tuple, closure_args) {
if expected_tuple != found || pats.len() != found {
err.span_label(span, format!("takes {}", found_str));
} else {
let sugg = format!(
"|({}){}|",
pats.join(", "),
// add type annotations if available
if tys.iter().any(|ty| ty.is_some()) {
Cow::from(format!(
": ({})",
tys.into_iter().map(|ty| if let Some(ty) = ty {
ty
} else {
"_".to_string()
}).collect::<Vec<String>>().join(", ")
))
} else {
Cow::from("")
},
);
err.span_suggestion(
span,
"consider changing the closure to accept a tuple",
sugg
);
}
} else {
err.span_label(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);
}
}
@ -1331,3 +1319,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
suggested_limit));
}
}
enum ArgKind {
Arg(String, String),
Tuple(Span, Vec<(String, String)>),
}
impl ArgKind {
fn empty() -> ArgKind {
ArgKind::Arg("_".to_owned(), "_".to_owned())
}
}

View File

@ -15,6 +15,7 @@ pub fn target() -> TargetResult {
let mut base = super::cloudabi_base::opts();
base.max_atomic_width = Some(128);
base.abi_blacklist = super::arm_base::abi_blacklist();
base.linker = "aarch64-unknown-cloudabi-cc".to_string();
Ok(Target {
llvm_target: "aarch64-unknown-cloudabi".to_string(),

View File

@ -17,6 +17,7 @@ pub fn target() -> TargetResult {
base.max_atomic_width = Some(64);
base.features = "+v7,+vfp3,+neon".to_string();
base.abi_blacklist = super::arm_base::abi_blacklist();
base.linker = "armv7-unknown-cloudabi-eabihf-cc".to_string();
Ok(Target {
llvm_target: "armv7-unknown-cloudabi-eabihf".to_string(),

View File

@ -15,6 +15,7 @@ pub fn target() -> TargetResult {
let mut base = super::cloudabi_base::opts();
base.cpu = "pentium4".to_string();
base.max_atomic_width = Some(64);
base.linker = "i686-unknown-cloudabi-cc".to_string();
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
base.stack_probes = true;

View File

@ -15,6 +15,7 @@ pub fn target() -> TargetResult {
let mut base = super::cloudabi_base::opts();
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);
base.linker = "x86_64-unknown-cloudabi-cc".to_string();
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
base.stack_probes = true;

View File

@ -94,20 +94,22 @@ r##"<!DOCTYPE html>
<h2>Keyboard Shortcuts</h2>
<dl>
<dt>?</dt>
<dt><kbd>?</kbd></dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dt><kbd>S</kbd></dt>
<dd>Focus the search field</dd>
<dt></dt>
<dt><kbd></kbd></dt>
<dd>Move up in search results</dd>
<dt></dt>
<dt><kbd></kbd></dt>
<dd>Move down in search results</dd>
<dt></dt>
<dt><kbd></kbd></dt>
<dd>Switch tab</dd>
<dt>&#9166;</dt>
<dt><kbd>&#9166;</kbd></dt>
<dd>Go to active search result</dd>
<dt style="width:31px;">+ / -</dt>
<dd>Collapse/expand all sections</dd>
<dt><kbd>+</kbd></dt>
<dd>Expand all sections</dd>
<dt><kbd>-</kbd></dt>
<dd>Collapse all sections</dd>
</dl>
</div>

View File

@ -585,18 +585,13 @@ body.blur > :not(#help) {
flex: 0 0 auto;
box-shadow: 0 0 6px rgba(0,0,0,.2);
width: 550px;
height: 354px;
height: auto;
border: 1px solid;
}
#help dt {
float: left;
border-radius: 4px;
border: 1px solid;
width: 23px;
text-align: center;
clear: left;
display: block;
margin-top: -1px;
}
#help dd { margin: 5px 35px; }
#help .infos { padding-left: 0; }
@ -1134,3 +1129,14 @@ h3.important {
left: -42px;
margin-top: 2px;
}
kbd {
display: inline-block;
padding: 3px 5px;
font: 15px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
line-height: 10px;
vertical-align: middle;
border: solid 1px;
border-radius: 3px;
box-shadow: inset 0 -1px 0;
}

View File

@ -194,11 +194,6 @@ a.test-arrow {
border-color: #bfbfbf;
}
#help dt {
border-color: #bfbfbf;
background: #fff;
}
.since {
color: grey;
}
@ -348,3 +343,11 @@ pre.ignore:hover, .information:hover + pre.ignore {
border-bottom-color: #e0e0e0;
}
}
kbd {
color: #444d56;
background-color: #fafbfc;
border-color: #d1d5da;
border-bottom-color: #c6cbd1;
box-shadow-color: #c6cbd1;
}

View File

@ -64,11 +64,11 @@
//! * You want a map, with no extra functionality.
//!
//! ### Use a `BTreeMap` when:
//! * You want a map sorted by its keys.
//! * You want to be able to get a range of entries on-demand.
//! * You're interested in what the smallest or largest key-value pair is.
//! * You want to find the largest or smallest key that is smaller or larger
//! than something.
//! * You want to be able to get all of the entries in order on-demand.
//! * You want a map sorted by its keys.
//!
//! ### Use the `Set` variant of any of these `Map`s when:
//! * You just want to remember which keys you've seen.

View File

@ -12,7 +12,9 @@ use fmt;
use hash;
use io;
use mem;
use net::{lookup_host, ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
use net::{ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
#[allow(deprecated)]
use net::lookup_host;
use option;
use sys::net::netc as c;
use sys_common::{FromInner, AsInner, IntoInner};
@ -845,6 +847,7 @@ impl ToSocketAddrs for (Ipv6Addr, u16) {
}
}
#[allow(deprecated)]
fn resolve_socket_addr(s: &str, p: u16) -> io::Result<vec::IntoIter<SocketAddr>> {
let ips = lookup_host(s)?;
let v: Vec<_> = ips.map(|mut a| { a.set_port(p); a }).collect();

View File

@ -134,12 +134,15 @@ fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
iterator and returning socket \
addresses",
issue = "27705")]
#[rustc_deprecated(since = "1.25", reason = "Use the ToSocketAddrs trait instead")]
pub struct LookupHost(net_imp::LookupHost);
#[unstable(feature = "lookup_host", reason = "unsure about the returned \
iterator and returning socket \
addresses",
issue = "27705")]
#[rustc_deprecated(since = "1.25", reason = "Use the ToSocketAddrs trait instead")]
#[allow(deprecated)]
impl Iterator for LookupHost {
type Item = SocketAddr;
fn next(&mut self) -> Option<SocketAddr> { self.0.next() }
@ -149,6 +152,8 @@ impl Iterator for LookupHost {
iterator and returning socket \
addresses",
issue = "27705")]
#[rustc_deprecated(since = "1.25", reason = "Use the ToSocketAddrs trait instead")]
#[allow(deprecated)]
impl fmt::Debug for LookupHost {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("LookupHost { .. }")
@ -181,6 +186,8 @@ impl fmt::Debug for LookupHost {
iterator and returning socket \
addresses",
issue = "27705")]
#[rustc_deprecated(since = "1.25", reason = "Use the ToSocketAddrs trait instead")]
#[allow(deprecated)]
pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
net_imp::lookup_host(host).map(LookupHost)
}

View File

@ -1869,7 +1869,11 @@ impl Path {
///
/// let path = Path::new("/test/haha/foo.txt");
///
/// assert_eq!(path.strip_prefix("/"), Ok(Path::new("test/haha/foo.txt")));
/// assert_eq!(path.strip_prefix("/test"), Ok(Path::new("haha/foo.txt")));
/// assert_eq!(path.strip_prefix("/test/"), Ok(Path::new("haha/foo.txt")));
/// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Path::new("")));
/// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Path::new("")));
/// assert_eq!(path.strip_prefix("test").is_ok(), false);
/// assert_eq!(path.strip_prefix("/haha").is_ok(), false);
/// ```
@ -1900,6 +1904,9 @@ impl Path {
/// let path = Path::new("/etc/passwd");
///
/// assert!(path.starts_with("/etc"));
/// assert!(path.starts_with("/etc/"));
/// assert!(path.starts_with("/etc/passwd"));
/// assert!(path.starts_with("/etc/passwd/"));
///
/// assert!(!path.starts_with("/e"));
/// ```

View File

@ -0,0 +1,57 @@
// 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(transpose_result)]
#[derive(Copy, Clone, Debug, PartialEq)]
struct BadNumErr;
fn try_num(x: i32) -> Result<i32, BadNumErr> {
if x <= 5 {
Ok(x + 1)
} else {
Err(BadNumErr)
}
}
type ResOpt = Result<Option<i32>, BadNumErr>;
type OptRes = Option<Result<i32, BadNumErr>>;
fn main() {
let mut x: ResOpt = Ok(Some(5));
let mut y: OptRes = Some(Ok(5));
assert_eq!(x, y.transpose());
assert_eq!(x.transpose(), y);
x = Ok(None);
y = None;
assert_eq!(x, y.transpose());
assert_eq!(x.transpose(), y);
x = Err(BadNumErr);
y = Some(Err(BadNumErr));
assert_eq!(x, y.transpose());
assert_eq!(x.transpose(), y);
let res: Result<Vec<i32>, BadNumErr> =
(0..10)
.map(|x| {
let y = try_num(x)?;
Ok(if y % 2 == 0 {
Some(y - 1)
} else {
None
})
})
.filter_map(Result::transpose)
.collect();
assert_eq!(res, Err(BadNumErr))
}

View File

@ -18,6 +18,8 @@ fn main() {
//~^ ERROR closure is expected to take
[1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
//~^ ERROR closure is expected to take
[1, 2, 3].sort_by(|(tuple, tuple2): (usize, _)| panic!());
//~^ ERROR closure is expected to take
f(|| panic!());
//~^ ERROR closure is expected to take
@ -32,6 +34,9 @@ fn main() {
let bar = |i, x, y| i;
let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
//~^ ERROR closure is expected to take
let _it = vec![1, 2, 3].into_iter().enumerate().map(qux);
//~^ ERROR function is expected to take
}
fn foo() {}
fn qux(x: usize, y: usize) {}

View File

@ -14,18 +14,34 @@ error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument
| |
| expected closure that takes 2 arguments
error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument
error[E0593]: closure is expected to take 2 distinct arguments, but it takes a single 2-tuple as argument
--> $DIR/closure-arg-count.rs:19:15
|
19 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
| ^^^^^^^ ----------------- takes 1 argument
| ^^^^^^^ ----------------- takes a single 2-tuple as argument
| |
| expected closure that takes 2 arguments
| expected closure that takes 2 distinct arguments
help: change the closure to take multiple arguments instead of a single tuple
|
19 | [1, 2, 3].sort_by(|tuple, tuple2| panic!());
| ^^^^^^^^^^^^^^^
error[E0593]: closure is expected to take 2 distinct arguments, but it takes a single 2-tuple as argument
--> $DIR/closure-arg-count.rs:21:15
|
21 | [1, 2, 3].sort_by(|(tuple, tuple2): (usize, _)| panic!());
| ^^^^^^^ ----------------------------- takes a single 2-tuple as argument
| |
| expected closure that takes 2 distinct arguments
help: change the closure to take multiple arguments instead of a single tuple
|
21 | [1, 2, 3].sort_by(|tuple, tuple2| panic!());
| ^^^^^^^^^^^^^^^
error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments
--> $DIR/closure-arg-count.rs:21:5
--> $DIR/closure-arg-count.rs:23:5
|
21 | f(|| panic!());
23 | f(|| panic!());
| ^ -- takes 0 arguments
| |
| expected closure that takes 1 argument
@ -36,46 +52,63 @@ note: required by `f`
13 | fn f<F: Fn<usize>>(_: F) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^
error[E0593]: closure is expected to take a single tuple as argument, but it takes 2 distinct arguments
--> $DIR/closure-arg-count.rs:24:53
|
24 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i);
| ^^^ ------ help: consider changing the closure to accept a tuple: `|(i, x)|`
| |
| expected closure that takes a single tuple as argument
error[E0593]: closure is expected to take a single tuple as argument, but it takes 2 distinct arguments
error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
--> $DIR/closure-arg-count.rs:26:53
|
26 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i);
| ^^^ ------------- help: consider changing the closure to accept a tuple: `|(i, x): (usize, _)|`
26 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i);
| ^^^ ------ takes 2 distinct arguments
| |
| expected closure that takes a single tuple as argument
| expected closure that takes a single 2-tuple as argument
help: change the closure to accept a tuple instead of individual arguments
|
26 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i);
| ^^^^^^^^
error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
--> $DIR/closure-arg-count.rs:28:53
|
28 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i);
28 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i);
| ^^^ ------------- takes 2 distinct arguments
| |
| expected closure that takes a single 2-tuple as argument
help: change the closure to accept a tuple instead of individual arguments
|
28 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i);
| ^^^^^^^^
error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
--> $DIR/closure-arg-count.rs:30:53
|
30 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i);
| ^^^ --------- takes 3 distinct arguments
| |
| expected closure that takes a single 2-tuple as argument
error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 0 arguments
--> $DIR/closure-arg-count.rs:30:53
--> $DIR/closure-arg-count.rs:32:53
|
30 | let _it = vec![1, 2, 3].into_iter().enumerate().map(foo);
32 | let _it = vec![1, 2, 3].into_iter().enumerate().map(foo);
| ^^^ expected function that takes a single 2-tuple as argument
...
37 | fn foo() {}
41 | fn foo() {}
| -------- takes 0 arguments
error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
--> $DIR/closure-arg-count.rs:33:53
--> $DIR/closure-arg-count.rs:35:53
|
32 | let bar = |i, x, y| i;
34 | let bar = |i, x, y| i;
| --------- takes 3 distinct arguments
33 | let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
35 | let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
| ^^^ expected closure that takes a single 2-tuple as argument
error: aborting due to 9 previous errors
error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
--> $DIR/closure-arg-count.rs:37:53
|
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) {}
| -------------------------- takes 2 distinct arguments
error: aborting due to 11 previous errors

View File

@ -69,6 +69,7 @@ fn filter_dirs(path: &Path) -> bool {
"src/tools/miri",
"src/librustc/mir/interpret",
"src/librustc_mir/interpret",
"src/target",
];
skip.iter().any(|p| path.ends_with(p))
}