From 176624fb4bcc7702a2a0cd859fccc3dec8e2f1ae Mon Sep 17 00:00:00 2001 From: Marcel Hellwig <921462+hellow554@users.noreply.github.com> Date: Thu, 21 Dec 2017 17:10:45 +0100 Subject: [PATCH 01/13] add kbd style tag to main.css in rustdoc --- src/librustdoc/html/static/rustdoc.css | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index e620abea277..c5d1ced0db9 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1107,3 +1107,17 @@ h3.important { left: -42px; margin-top: 2px; } + +kbd { + display: inline-block; + padding: 3px 5px; + font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; + line-height: 10px; + color: #444d56; + vertical-align: middle; + background-color: #fafbfc; + border: solid 1px #d1d5da; + border-bottom-color: #c6cbd1; + border-radius: 3px; + box-shadow: inset 0 -1px 0 #c6cbd1; +} From 6e741df1bd252e9b9d9972dc7f689890686a2b1e Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Fri, 22 Dec 2017 13:29:02 +0100 Subject: [PATCH 02/13] moved colors of kbd tag into main.css --- src/librustdoc/html/static/rustdoc.css | 7 ++----- src/librustdoc/html/static/styles/main.css | 9 +++++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index c5d1ced0db9..40df2cb7617 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1113,11 +1113,8 @@ kbd { padding: 3px 5px; font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; line-height: 10px; - color: #444d56; vertical-align: middle; - background-color: #fafbfc; - border: solid 1px #d1d5da; - border-bottom-color: #c6cbd1; + border: solid 1px; border-radius: 3px; - box-shadow: inset 0 -1px 0 #c6cbd1; + box-shadow: inset 0 -1px 0; } diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css index c31808cfc0f..df8facccafa 100644 --- a/src/librustdoc/html/static/styles/main.css +++ b/src/librustdoc/html/static/styles/main.css @@ -343,3 +343,12 @@ pre.ignore:hover, .information:hover + pre.ignore { border-right-color: #000; } } + +kbd { + color: #444d56; + background-color: #fafbfc; + border-color: #d1d5da; + border-bottom-color: #c6cbd1; + box-shadow-color: #c6cbd1; +} + From c9ae249265c5da207ba0d8a2f8be95e58817e1dc Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Thu, 4 Jan 2018 11:34:03 -0800 Subject: [PATCH 03/13] Add transpose conversions for Option and Result These impls are useful when working with combinator methods that expect an option or a result, but you have a Result, E> instead of an Option> or vice versa. --- src/libcore/option.rs | 29 +++++++++++ src/libcore/result.rs | 29 +++++++++++ src/test/run-pass/result-opt-conversions.rs | 57 +++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 src/test/run-pass/result-opt-conversions.rs diff --git a/src/libcore/option.rs b/src/libcore/option.rs index d8f3ec38cf3..76cea587038 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -884,6 +884,35 @@ impl Option { } } +impl Option> { + /// 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, SomeErr> = Ok(Some(5)); + /// let y: Option> = Some(Ok(5)); + /// assert_eq!(x, y.transpose()); + /// ``` + #[inline] + #[unstable(feature = "transpose_result", issue = "47338")] + pub fn transpose(self) -> Result, 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] diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 2ace3d2aee8..3801db94e15 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -909,6 +909,35 @@ impl Result { } } +impl Result, 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, SomeErr> = Ok(Some(5)); + /// let y: Option> = Some(Ok(5)); + /// assert_eq!(x.transpose(), y); + /// ``` + #[inline] + #[unstable(feature = "transpose_result", issue = "47338")] + pub fn transpose(self) -> Option> { + 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] diff --git a/src/test/run-pass/result-opt-conversions.rs b/src/test/run-pass/result-opt-conversions.rs new file mode 100644 index 00000000000..0f6da002dda --- /dev/null +++ b/src/test/run-pass/result-opt-conversions.rs @@ -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 or the MIT license +// , 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 { + if x <= 5 { + Ok(x + 1) + } else { + Err(BadNumErr) + } +} + +type ResOpt = Result, BadNumErr>; +type OptRes = Option>; + +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, 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)) +} From 38e5d304fe72a49dc6fbac1870546620e3557680 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Mon, 15 Jan 2018 18:12:38 +0100 Subject: [PATCH 04/13] extended dt with kbd tags removed styling of dt tages, which would make them look like keys and added tag inside of dt tag. Added css style for kbd and removed some stylings for dt --- src/librustdoc/html/layout.rs | 18 ++++++++++-------- src/librustdoc/html/static/rustdoc.css | 15 +++++---------- src/librustdoc/html/static/styles/main.css | 5 ----- 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 61de5f4bc4c..3a18c6b8a80 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -94,20 +94,22 @@ r##"

Keyboard Shortcuts

-
?
+
?
Show this help dialog
-
S
+
S
Focus the search field
-
+
Move up in search results
-
+
Move down in search results
-
+
Switch tab
-
+
Go to active search result
-
+ / -
-
Collapse/expand all sections
+
+
+
Expand all sections
+
-
+
Collapse all sections
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 40df2cb7617..bc2a5e663a1 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -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; + float: left; + clear: left; + display: block; } #help dd { margin: 5px 35px; } #help .infos { padding-left: 0; } @@ -1111,7 +1106,7 @@ h3.important { kbd { display: inline-block; padding: 3px 5px; - font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; + font: 15px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; line-height: 10px; vertical-align: middle; border: solid 1px; diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css index df8facccafa..e28a328cca6 100644 --- a/src/librustdoc/html/static/styles/main.css +++ b/src/librustdoc/html/static/styles/main.css @@ -194,11 +194,6 @@ a.test-arrow { border-color: #bfbfbf;; } -#help dt { - border-color: #bfbfbf; - background: #fff; -} - .since { color: grey; } From 0e1ecbed8364716d131a466b3e3f09e74e52385e Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 16 Jan 2018 19:35:39 -0600 Subject: [PATCH 05/13] add Rust By Example to the bookshelf --- src/doc/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/doc/index.md b/src/doc/index.md index 3784cc3c4b4..3add2774105 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -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 From 1b9c65694354b6507627d4f1662a9123de9b764a Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Thu, 18 Jan 2018 01:22:20 +0100 Subject: [PATCH 06/13] Add some edge cases to the documentation of `Path` Affected methods are `starts_with` and `strip_prefix`. --- src/libstd/path.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 7631a9a44bb..ed102c2949e 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -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")); /// ``` From 908aa388f9f0745f133a044d75e8c994c17f3152 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 16 Jan 2018 20:54:48 -0800 Subject: [PATCH 07/13] Deprecate std::net::lookup_host We intended to do this quite a while ago but it snuck through. --- src/libstd/net/addr.rs | 5 ++++- src/libstd/net/mod.rs | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index 1ca7e66ed9c..fa430939f05 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -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> { let ips = lookup_host(s)?; let v: Vec<_> = ips.map(|mut a| { a.set_port(p); a }).collect(); diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index 9fcb93e2032..eb0e2e13b4c 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -134,12 +134,15 @@ fn each_addr(addr: A, mut f: F) -> io::Result 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 { 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 { net_imp::lookup_host(host).map(LookupHost) } From 0c946c01795b8a3c05273805764ca5d90cb1af60 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Thu, 18 Jan 2018 09:06:55 +0100 Subject: [PATCH 08/13] converted space to tab in css files --- src/librustdoc/html/static/rustdoc.css | 6 +++--- src/librustdoc/html/static/styles/main.css | 11 +++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index bc2a5e663a1..0f972927d8e 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -589,9 +589,9 @@ body.blur > :not(#help) { border: 1px solid; } #help dt { - float: left; - clear: left; - display: block; + float: left; + clear: left; + display: block; } #help dd { margin: 5px 35px; } #help .infos { padding-left: 0; } diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css index e28a328cca6..d4964376af2 100644 --- a/src/librustdoc/html/static/styles/main.css +++ b/src/librustdoc/html/static/styles/main.css @@ -340,10 +340,9 @@ pre.ignore:hover, .information:hover + pre.ignore { } kbd { - color: #444d56; - background-color: #fafbfc; - border-color: #d1d5da; - border-bottom-color: #c6cbd1; - box-shadow-color: #c6cbd1; + color: #444d56; + background-color: #fafbfc; + border-color: #d1d5da; + border-bottom-color: #c6cbd1; + box-shadow-color: #c6cbd1; } - From 005791b33f3f7a0f725065d580b89f0286c31236 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 18 Jan 2018 11:02:32 +0530 Subject: [PATCH 09/13] add target/ to ignored tidy dirs --- src/tools/tidy/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 61d71986b03..eee2902bfb6 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -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)) } From 9a4287d263748970ee1bf7ba116bbc5225962a4f Mon Sep 17 00:00:00 2001 From: Matthew Walinga Date: Thu, 18 Jan 2018 18:05:33 -0500 Subject: [PATCH 10/13] Update CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 54c507304f9..70376c120fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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. From 8d7f554a7fa0746bf84c118e7060d8c36487ac9e Mon Sep 17 00:00:00 2001 From: Ed Schouten Date: Fri, 19 Jan 2018 09:29:58 +0100 Subject: [PATCH 11/13] Give TargetOptions::linker a sane default value. Though some parts of rust use cc-rs to invoke a compiler/linker, Cargo seems to make use of the TargetOptions::linker property. Make the out of the box experience for CloudABI a bit better by using the same compiler name as cc-rs. --- src/librustc_back/target/aarch64_unknown_cloudabi.rs | 1 + src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs | 1 + src/librustc_back/target/i686_unknown_cloudabi.rs | 1 + src/librustc_back/target/x86_64_unknown_cloudabi.rs | 1 + 4 files changed, 4 insertions(+) diff --git a/src/librustc_back/target/aarch64_unknown_cloudabi.rs b/src/librustc_back/target/aarch64_unknown_cloudabi.rs index d5e8194c3f7..59c82e06a67 100644 --- a/src/librustc_back/target/aarch64_unknown_cloudabi.rs +++ b/src/librustc_back/target/aarch64_unknown_cloudabi.rs @@ -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(), diff --git a/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs b/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs index 4dad8e1713b..faa2c4fdceb 100644 --- a/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs +++ b/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs @@ -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(), diff --git a/src/librustc_back/target/i686_unknown_cloudabi.rs b/src/librustc_back/target/i686_unknown_cloudabi.rs index b9aa6176d87..e244f443d3e 100644 --- a/src/librustc_back/target/i686_unknown_cloudabi.rs +++ b/src/librustc_back/target/i686_unknown_cloudabi.rs @@ -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; diff --git a/src/librustc_back/target/x86_64_unknown_cloudabi.rs b/src/librustc_back/target/x86_64_unknown_cloudabi.rs index f9a563174d4..1ce3c6444f1 100644 --- a/src/librustc_back/target/x86_64_unknown_cloudabi.rs +++ b/src/librustc_back/target/x86_64_unknown_cloudabi.rs @@ -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; From fdf444da766715ec6bb181eb12b553333e925eb4 Mon Sep 17 00:00:00 2001 From: Arthur Silva Date: Fri, 19 Jan 2018 15:40:02 +0100 Subject: [PATCH 12/13] Update BTreeMap recommendation Focus on the ordering/range benefit. --- src/libstd/collections/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index b8a6a66eaa6..e9a150f34a5 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -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. From 7ed00caacc6801c8d99bcb5754a22209e9bfe661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 19 Jan 2018 01:28:20 -0800 Subject: [PATCH 13/13] Closure argument mismatch tweaks - use consistent phrasing for expected and found arguments - suggest changing arugments to tuple if possible - suggest changing single tuple argument to arguments if possible --- src/librustc/traits/error_reporting.rs | 301 +++++++++--------- .../ui/mismatched_types/closure-arg-count.rs | 5 + .../mismatched_types/closure-arg-count.stderr | 85 +++-- 3 files changed, 214 insertions(+), 177 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 54da23821f5..dd603378221 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -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![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::>() + ), + _ => 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::>>(); + .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::>>(); - - 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) { + 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::>(), + ) + } else { + let name = self.tcx.sess.codemap().span_to_snippet(arg.pat.span).unwrap(); + ArgKind::Arg(name, "_".to_owned()) + } + }) + .collect::>()) + } 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::>(), + ), + _ => ArgKind::Arg("_".to_owned(), "_".to_owned()) + }).collect::>()) + } else { + panic!("non-FnLike node found: {:?}", node); + } + } + fn report_arg_count_mismatch( &self, span: Span, - found_span: Option, - expected: usize, - expected_tuple: Option, - found: usize, - closure_args: Option<(Vec, Vec>)>, - is_closure: bool + found_span: Span, + expected_args: Vec, + found_args: Vec, + 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, other: &Vec| { + 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::>().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::>().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); } } @@ -1325,3 +1313,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()) + } +} diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs index 1ee24e39852..96e5201716c 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.rs +++ b/src/test/ui/mismatched_types/closure-arg-count.rs @@ -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) {} diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 216f39bac54..d904831ba4e 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -14,64 +14,97 @@ 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 | = note: required by `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