mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-04 02:54:00 +00:00
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:
commit
8d3e93beae
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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>⏎</dt>
|
||||
<dt><kbd>⏎</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>
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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"));
|
||||
/// ```
|
||||
|
57
src/test/run-pass/result-opt-conversions.rs
Normal file
57
src/test/run-pass/result-opt-conversions.rs
Normal 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))
|
||||
}
|
@ -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) {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user