From 20a795e6c6be5b27e16df257f104f5f26ab730e9 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Sun, 15 Apr 2018 17:07:39 -0400 Subject: [PATCH 01/18] Mention Result in never docs. --- src/libstd/primitive_docs.rs | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index ce4bbfffc2e47..8905f7c9e1605 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -112,6 +112,8 @@ mod prim_bool { } /// /// # `!` and generics /// +/// ## Infalliable errors +/// /// The main place you'll see `!` used explicitly is in generic code. Consider the [`FromStr`] /// trait: /// @@ -140,9 +142,59 @@ mod prim_bool { } /// [`Ok`] variant. This illustrates another behaviour of `!` - it can be used to "delete" certain /// enum variants from generic types like `Result`. /// +/// ## Infinite loops +/// +/// While [`Result`] is very useful for removing errors, `!` can also be used to removed +/// successes as well. If we think of [`Result`] as "if this function returns, it has not +/// errored," we get a very intuitive idea of [`Result`] as well: if the function returns, it +/// *has* errored. +/// +/// For example, consider the case of a simple web server, which can be simplified to: +/// +/// ```ignore (hypothetical-example) +/// loop { +/// let (client, request) = get_request().expect("disconnected"); +/// let response = request.process(); +/// response.send(client); +/// } +/// ``` +/// +/// Currently, this isn't ideal, because we simply panic whenever we fail to get a new connection. +/// Instead, we'd like to keep track of this error, like this: +/// +/// ```ignore (hypothetical-example) +/// loop { +/// match get_request() { +/// Err(err) => break err, +/// Ok((client, request)) => { +/// let response = request.process(); +/// response.send(client); +/// }, +/// } +/// } +/// ``` +/// +/// Now, when the server disconnects, we exit the loop with an error instead of panicking. While it +/// might be intuitive to simply return the error, we might want to wrap it in a [`Result`] +/// instead: +/// +/// ```ignore (hypothetical-example) +/// fn server_loop() -> Result { +/// Ok(loop { +/// let (client, request) = get_request()?; +/// let response = request.process(); +/// response.send(client); +/// }) +/// } +/// ``` +/// +/// Now, we can use `?` instead of `match`, and the return type makes a lot more sense: if the loop +/// ever stops, it means that an error occurred. +/// /// [`String::from_str`]: str/trait.FromStr.html#tymethod.from_str /// [`Result`]: result/enum.Result.html /// [`Result`]: result/enum.Result.html +/// [`Result`]: result/enum.Result.html /// [`Ok`]: result/enum.Result.html#variant.Ok /// [`String`]: string/struct.String.html /// [`Err`]: result/enum.Result.html#variant.Err From 2843e648c236c0ed31f0155f0805f43f3ee7ed95 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 21 Apr 2018 23:22:27 +0200 Subject: [PATCH 02/18] turn `ManuallyDrop::new` into a constant function --- src/libcore/mem.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index e3f08926610f6..6d64d91312e0f 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -960,7 +960,7 @@ impl ManuallyDrop { /// ``` #[stable(feature = "manually_drop", since = "1.20.0")] #[inline] - pub fn new(value: T) -> ManuallyDrop { + pub const fn new(value: T) -> ManuallyDrop { ManuallyDrop { value: value } } From 4b444f5b2393d23e980ea0042f976e01c752cfc0 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Tue, 1 May 2018 13:49:31 +0100 Subject: [PATCH 03/18] Updated RELEASES.md for 1.26.0 --- RELEASES.md | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 39cef1e2a5770..32c83c0d64926 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,211 @@ +Version 1.26.0 (2018-05-10) +========================== + +Language +-------- +- [Closures now implement `Copy` and/or `Clone` if all captured variables + implement either or both traits.][49299] +- [The inclusive range syntax e.g. `for x in 0..=10` is now stable.][47813] +- [Stablise `'_`. The underscore lifetime can be used anywhere where a + lifetime can be elided.][49458] +- [`impl Trait` is now stable allowing you to have abstract + return types.][49255] e.g. `fn foo() -> impl Iterator` or + `fn open(path: impl AsRef)`. +- [Pattern matching will now automatically apply dereferences.][49394] +- [128-bit integers in the form of `u128` and `i128` are now stable.][49101] +- [`main` can now return `Result<(), E: Debug>`][49162] in addition to `()`. +- [Fixed entry slice patterns are now stable.][48516] e.g. + ```rust + let points = [1, 2, 3, 4]; + match points { + [1, 2, 3, 4] => println!("All points were sequential."), + _ => println!("Not all points were sequential."), + } + ``` + + +Compiler +-------- +- [LLD is now used as the default linker for `wasm32-unknown-unknown`.][48125] +- [Fixed exponential projection complexity on nested types.][48296] + This can provide up to a ~12% reduction in compile times for certain crates. +- [Added the `--remap-path-prefix` option to rustc.][48359] Allowing you + to remap path prefixes outputted by the compiler. +- [Added `powerpc-unknown-netbsd` target.][48281] + +Libraries +--------- +- [Implemented `From for usize` & `From<{u8, i16}> for isize`.][49305] +- [Added hexadecimal formatting for integers with fmt::Debug][48978] + e.g. `assert!(format!("{:02x?}", b"Foo\0") == "[46, 6f, 6f, 00]")` +- [Implemented `Default, Hash` for `cmp::Reverse`.][48628] +- [Optimized `str::repeat` being 8x faster in large cases.][48657] +- [`ascii::escape_default` is now available in libcore.][48735] +- [Implemented `FromStr` for `PathBuf`][48292] +- [Trailing commas are now supported in std and core macros.][48056] +- [Implemented `Copy, Clone` for `cmp::Reverse`][47379] +- [Implemented `Clone` for `char::{ToLowercase, ToUppercase}`.][48629] + +Stabilized APIs +--------------- +- [`*const T::add`] +- [`*const T::copy_to_nonoverlapping`] +- [`*const T::copy_to`] +- [`*const T::read_unaligned`] +- [`*const T::read_volatile`] +- [`*const T::read`] +- [`*const T::sub`] +- [`*const T::wrapping_add`] +- [`*const T::wrapping_sub`] +- [`*mut T::add`] +- [`*mut T::copy_to_nonoverlapping`] +- [`*mut T::copy_to`] +- [`*mut T::read_unaligned`] +- [`*mut T::read_volatile`] +- [`*mut T::read`] +- [`*mut T::replace`] +- [`*mut T::sub`] +- [`*mut T::swap`] +- [`*mut T::wrapping_add`] +- [`*mut T::wrapping_sub`] +- [`*mut T::write_bytes`] +- [`*mut T::write_unaligned`] +- [`*mut T::write_volatile`] +- [`*mut T::write`] +- [`Box::leak`] +- [`FromUtf8Error::as_bytes`] +- [`LocalKey::try_with`] +- [`Option::cloned`] +- [`btree_map::Entry::and_modify`] +- [`convert::TryFrom`] +- [`convert::TryInto`] +- [`fs::read_to_string`] +- [`fs::read`] +- [`fs::write`] +- [`hash_map::Entry::and_modify`] +- [`iter::FusedIterator`] +- [`ops::RangeInclusive`] +- [`ops::RangeToInclusive`] +- [`process::id`] +- [`slice::rotate_left`] +- [`slice::rotate_right`] +- [`String::retain`] + + +Cargo +----- +- [Cargo will now output path to custom commands when `-v` is + passed with `--list`][cargo/5041] +- [The Cargo binary version is now the same as the Rust version][cargo/5083] +- [`Cargo.lock` files are now included in published crates.][cargo/5093] + +Misc +---- +- [The second edition of "The Rust Programming Language" book is now recommended + over the first.][48404] + +Compatibility Notes +------------------- + +- [aliasing a `Fn` trait as `dyn` no longer works.][48481] E.g. the following + syntax is now invalid. + ``` + use std::ops::Fn as dyn; + fn g(_: Box) {} + ``` +- [The result of dereferences are no longer promoted to `'static`.][47408] + e.g. + ```rust + fn main() { + const PAIR: &(i32, i32) = &(0, 1); + let _reversed_pair: &'static _ = &(PAIR.1, PAIR.0); // Doesn't work + } + ``` +- [Removed the deprecated unstable `SipHasher{13,24}` from documentation.][49108] +- [Deprecate `AsciiExt` trait in favor of inherent methods.][49109] +- [`".e0"` will now no longer parse as `0.0` and will instead cause + an error.][48235] +- [Removed hoedown from rustdoc.][48274] + +[47379]: https://github.com/rust-lang/rust/pull/47379 +[47408]: https://github.com/rust-lang/rust/pull/47408 +[47813]: https://github.com/rust-lang/rust/pull/47813 +[48056]: https://github.com/rust-lang/rust/pull/48056 +[48125]: https://github.com/rust-lang/rust/pull/48125 +[48166]: https://github.com/rust-lang/rust/pull/48166 +[48235]: https://github.com/rust-lang/rust/pull/48235 +[48274]: https://github.com/rust-lang/rust/pull/48274 +[48281]: https://github.com/rust-lang/rust/pull/48281 +[48292]: https://github.com/rust-lang/rust/pull/48292 +[48296]: https://github.com/rust-lang/rust/pull/48296 +[48359]: https://github.com/rust-lang/rust/pull/48359 +[48404]: https://github.com/rust-lang/rust/pull/48404 +[48481]: https://github.com/rust-lang/rust/pull/48481 +[48516]: https://github.com/rust-lang/rust/pull/48516 +[48628]: https://github.com/rust-lang/rust/pull/48628 +[48629]: https://github.com/rust-lang/rust/pull/48629 +[48657]: https://github.com/rust-lang/rust/pull/48657 +[48735]: https://github.com/rust-lang/rust/pull/48735 +[48978]: https://github.com/rust-lang/rust/pull/48978 +[49101]: https://github.com/rust-lang/rust/pull/49101 +[49108]: https://github.com/rust-lang/rust/pull/49108 +[49109]: https://github.com/rust-lang/rust/pull/49109 +[49121]: https://github.com/rust-lang/rust/pull/49121 +[49162]: https://github.com/rust-lang/rust/pull/49162 +[49184]: https://github.com/rust-lang/rust/pull/49184 +[49234]: https://github.com/rust-lang/rust/pull/49234 +[49255]: https://github.com/rust-lang/rust/pull/49255 +[49299]: https://github.com/rust-lang/rust/pull/49299 +[49305]: https://github.com/rust-lang/rust/pull/49305 +[49394]: https://github.com/rust-lang/rust/pull/49394 +[49458]: https://github.com/rust-lang/rust/pull/49458 +[`*const T::add`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.add +[`*const T::copy_to_nonoverlapping`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.copy_to_nonoverlapping +[`*const T::copy_to`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.copy_to +[`*const T::read_unaligned`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.read_unaligned +[`*const T::read_volatile`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.read_volatile +[`*const T::read`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.read +[`*const T::sub`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.sub +[`*const T::wrapping_add`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_add +[`*const T::wrapping_sub`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_sub +[`*mut T::add`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.add-1 +[`*mut T::copy_to_nonoverlapping`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.copy_to_nonoverlapping-1 +[`*mut T::copy_to`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.copy_to-1 +[`*mut T::read_unaligned`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.read_unaligned-1 +[`*mut T::read_volatile`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.read_volatile-1 +[`*mut T::read`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.read-1 +[`*mut T::replace`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.replace +[`*mut T::sub`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.sub-1 +[`*mut T::swap`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.swap +[`*mut T::wrapping_add`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_add-1 +[`*mut T::wrapping_sub`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_sub-1 +[`*mut T::write_bytes`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.write_bytes +[`*mut T::write_unaligned`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.write_unaligned +[`*mut T::write_volatile`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.write_volatile +[`*mut T::write`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.write +[`Box::leak`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.leak +[`FromUtf8Error::as_bytes`]: https://doc.rust-lang.org/std/string/struct.FromUtf8Error.html#method.as_bytes +[`LocalKey::try_with`]: https://doc.rust-lang.org/std/thread/struct.LocalKey.html#method.try_with +[`Option::cloned`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.cloned +[`btree_map::Entry::and_modify`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.and_modify +[`convert::TryFrom`]: https://doc.rust-lang.org/std/convert/trait.TryFrom.html +[`convert::TryInto`]: https://doc.rust-lang.org/std/convert/trait.TryInto.html +[`fs::read_to_string`]: https://doc.rust-lang.org/std/fs/fn.read_to_string.html +[`fs::read`]: https://doc.rust-lang.org/std/fs/fn.read.html +[`fs::write`]: https://doc.rust-lang.org/std/fs/fn.write.html +[`hash_map::Entry::and_modify`]: https://doc.rust-lang.org/std/collections/hash_map/enum.Entry.html#method.and_modify +[`iter::FusedIterator`]: https://doc.rust-lang.org/std/iter/trait.FusedIterator.html +[`ops::RangeInclusive`]: https://doc.rust-lang.org/std/ops/struct.RangeInclusive.html +[`ops::RangeToInclusive`]: https://doc.rust-lang.org/std/ops/struct.RangeToInclusive.html +[`process::id`]: https://doc.rust-lang.org/std/process/fn.id.html +[`slice::rotate_left`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rotate_left +[`slice::rotate_right`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rotate_right +[`String::retain`]: https://doc.rust-lang.org/std/string/struct.String.html#method.retain +[cargo/5041]: https://github.com/rust-lang/cargo/pull/5041 +[cargo/5083]: https://github.com/rust-lang/cargo/pull/5083 +[cargo/5093]: https://github.com/rust-lang/cargo/pull/5093 + + Version 1.25.0 (2018-03-29) ========================== From fc6d6c98dedca297c09016615011bee448e5e468 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Fri, 4 May 2018 21:37:28 -0400 Subject: [PATCH 04/18] Fixed typos --- src/libstd/primitive_docs.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 8905f7c9e1605..49344cab1dd26 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -112,7 +112,7 @@ mod prim_bool { } /// /// # `!` and generics /// -/// ## Infalliable errors +/// ## Infallible errors /// /// The main place you'll see `!` used explicitly is in generic code. Consider the [`FromStr`] /// trait: @@ -144,7 +144,7 @@ mod prim_bool { } /// /// ## Infinite loops /// -/// While [`Result`] is very useful for removing errors, `!` can also be used to removed +/// While [`Result`] is very useful for removing errors, `!` can also be used to remove /// successes as well. If we think of [`Result`] as "if this function returns, it has not /// errored," we get a very intuitive idea of [`Result`] as well: if the function returns, it /// *has* errored. @@ -175,21 +175,22 @@ mod prim_bool { } /// ``` /// /// Now, when the server disconnects, we exit the loop with an error instead of panicking. While it -/// might be intuitive to simply return the error, we might want to wrap it in a [`Result`] +/// might be intuitive to simply return the error, we might want to wrap it in a [`Result`] /// instead: /// /// ```ignore (hypothetical-example) /// fn server_loop() -> Result { -/// Ok(loop { +/// loop { /// let (client, request) = get_request()?; /// let response = request.process(); /// response.send(client); -/// }) +/// } /// } /// ``` /// /// Now, we can use `?` instead of `match`, and the return type makes a lot more sense: if the loop -/// ever stops, it means that an error occurred. +/// ever stops, it means that an error occurred. We don't even have to wrap the loop in an `Ok` +/// because `!` coerces to `Result` automatically. /// /// [`String::from_str`]: str/trait.FromStr.html#tymethod.from_str /// [`Result`]: result/enum.Result.html From 160063aad2206a35e6312bfaa159f0f4475af0ae Mon Sep 17 00:00:00 2001 From: F001 Date: Sat, 5 May 2018 16:34:43 +0800 Subject: [PATCH 05/18] make `String::new()` const --- src/liballoc/lib.rs | 1 + src/liballoc/string.rs | 3 ++- .../{vec-const-new.rs => collections-const-new.rs} | 7 ++++++- 3 files changed, 9 insertions(+), 2 deletions(-) rename src/test/run-pass/{vec-const-new.rs => collections-const-new.rs} (77%) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index da4b76a4d527d..bb78c14b90586 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -125,6 +125,7 @@ #![feature(inclusive_range_methods)] #![cfg_attr(stage0, feature(generic_param_attrs))] #![feature(rustc_const_unstable)] +#![feature(const_vec_new)] #![cfg_attr(not(test), feature(fn_traits, i128))] #![cfg_attr(test, feature(test))] diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 2f84d5f7f8676..da9afdd2ca37b 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -380,7 +380,8 @@ impl String { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> String { + #[rustc_const_unstable(feature = "const_string_new")] + pub const fn new() -> String { String { vec: Vec::new() } } diff --git a/src/test/run-pass/vec-const-new.rs b/src/test/run-pass/collections-const-new.rs similarity index 77% rename from src/test/run-pass/vec-const-new.rs rename to src/test/run-pass/collections-const-new.rs index 62e2a36d7cc77..4003c2ec4f7e4 100644 --- a/src/test/run-pass/vec-const-new.rs +++ b/src/test/run-pass/collections-const-new.rs @@ -8,10 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that Vec::new() can be used for constants +// Test several functions can be used for constants +// 1. Vec::new() +// 2. String::new() #![feature(const_vec_new)] +#![feature(const_string_new)] const MY_VEC: Vec = Vec::new(); +const MY_STRING: String = String::new(); + pub fn main() {} From 6c8ec842cc2dbd0f4dbf99dbd47717fb48cf5b88 Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 5 May 2018 19:45:22 +0200 Subject: [PATCH 06/18] Remove some transmutes --- src/libcore/tests/num/flt2dec/random.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/libcore/tests/num/flt2dec/random.rs b/src/libcore/tests/num/flt2dec/random.rs index 315ac4d7d99f5..a1928657dabc4 100644 --- a/src/libcore/tests/num/flt2dec/random.rs +++ b/src/libcore/tests/num/flt2dec/random.rs @@ -11,7 +11,6 @@ #![cfg(not(target_arch = "wasm32"))] use std::i16; -use std::mem; use std::str; use core::num::flt2dec::MAX_SIG_DIGITS; @@ -75,8 +74,7 @@ pub fn f32_random_equivalence_test(f: F, g: G, k: usize, n: usize) let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng()); let f32_range = Range::new(0x0000_0001u32, 0x7f80_0000); iterate("f32_random_equivalence_test", k, n, f, g, |_| { - let i: u32 = f32_range.ind_sample(&mut rng); - let x: f32 = unsafe {mem::transmute(i)}; + let x = f32::from_bits(f32_range.ind_sample(&mut rng)); decode_finite(x) }); } @@ -87,8 +85,7 @@ pub fn f64_random_equivalence_test(f: F, g: G, k: usize, n: usize) let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng()); let f64_range = Range::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000); iterate("f64_random_equivalence_test", k, n, f, g, |_| { - let i: u64 = f64_range.ind_sample(&mut rng); - let x: f64 = unsafe {mem::transmute(i)}; + let x = f64::from_bits(f64_range.ind_sample(&mut rng)); decode_finite(x) }); } @@ -105,7 +102,8 @@ pub fn f32_exhaustive_equivalence_test(f: F, g: G, k: usize) // iterate from 0x0000_0001 to 0x7f7f_ffff, i.e. all finite ranges let (npassed, nignored) = iterate("f32_exhaustive_equivalence_test", k, 0x7f7f_ffff, f, g, |i: usize| { - let x: f32 = unsafe {mem::transmute(i as u32 + 1)}; + + let x = f32::from_bits(i as u32 + 1); decode_finite(x) }); assert_eq!((npassed, nignored), (2121451881, 17643158)); From b61a4c20c6acd963070adb083b12d5e21a5843d3 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 7 May 2018 12:11:22 +0200 Subject: [PATCH 07/18] make the const constructor unstable --- src/libcore/mem.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 6d64d91312e0f..6836f8622b0ee 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -959,6 +959,7 @@ impl ManuallyDrop { /// ManuallyDrop::new(Box::new(())); /// ``` #[stable(feature = "manually_drop", since = "1.20.0")] + #[rustc_const_unstable(feature = "const_manually_drop_new")] #[inline] pub const fn new(value: T) -> ManuallyDrop { ManuallyDrop { value: value } From 85f3ecfa9b7cb3d1b481f82a627139905f74bb23 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Mon, 7 May 2018 11:37:36 +0100 Subject: [PATCH 08/18] Update RELEASES.md --- RELEASES.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 32c83c0d64926..ba9950e57c865 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -14,6 +14,9 @@ Language - [Pattern matching will now automatically apply dereferences.][49394] - [128-bit integers in the form of `u128` and `i128` are now stable.][49101] - [`main` can now return `Result<(), E: Debug>`][49162] in addition to `()`. +- [A lot of operations are now available in a const context.][46882] E.g. You + can now index into constant arrays, reference and deference into constants, + and use Tuple struct constructors. - [Fixed entry slice patterns are now stable.][48516] e.g. ```rust let points = [1, 2, 3, 4]; @@ -41,7 +44,6 @@ Libraries - [Implemented `Default, Hash` for `cmp::Reverse`.][48628] - [Optimized `str::repeat` being 8x faster in large cases.][48657] - [`ascii::escape_default` is now available in libcore.][48735] -- [Implemented `FromStr` for `PathBuf`][48292] - [Trailing commas are now supported in std and core macros.][48056] - [Implemented `Copy, Clone` for `cmp::Reverse`][47379] - [Implemented `Clone` for `char::{ToLowercase, ToUppercase}`.][48629] @@ -77,8 +79,6 @@ Stabilized APIs - [`LocalKey::try_with`] - [`Option::cloned`] - [`btree_map::Entry::and_modify`] -- [`convert::TryFrom`] -- [`convert::TryInto`] - [`fs::read_to_string`] - [`fs::read`] - [`fs::write`] @@ -121,12 +121,12 @@ Compatibility Notes let _reversed_pair: &'static _ = &(PAIR.1, PAIR.0); // Doesn't work } ``` -- [Removed the deprecated unstable `SipHasher{13,24}` from documentation.][49108] - [Deprecate `AsciiExt` trait in favor of inherent methods.][49109] - [`".e0"` will now no longer parse as `0.0` and will instead cause an error.][48235] - [Removed hoedown from rustdoc.][48274] +[46882]: https://github.com/rust-lang/rust/pull/46882 [47379]: https://github.com/rust-lang/rust/pull/47379 [47408]: https://github.com/rust-lang/rust/pull/47408 [47813]: https://github.com/rust-lang/rust/pull/47813 @@ -136,7 +136,6 @@ Compatibility Notes [48235]: https://github.com/rust-lang/rust/pull/48235 [48274]: https://github.com/rust-lang/rust/pull/48274 [48281]: https://github.com/rust-lang/rust/pull/48281 -[48292]: https://github.com/rust-lang/rust/pull/48292 [48296]: https://github.com/rust-lang/rust/pull/48296 [48359]: https://github.com/rust-lang/rust/pull/48359 [48404]: https://github.com/rust-lang/rust/pull/48404 @@ -148,7 +147,6 @@ Compatibility Notes [48735]: https://github.com/rust-lang/rust/pull/48735 [48978]: https://github.com/rust-lang/rust/pull/48978 [49101]: https://github.com/rust-lang/rust/pull/49101 -[49108]: https://github.com/rust-lang/rust/pull/49108 [49109]: https://github.com/rust-lang/rust/pull/49109 [49121]: https://github.com/rust-lang/rust/pull/49121 [49162]: https://github.com/rust-lang/rust/pull/49162 @@ -188,8 +186,6 @@ Compatibility Notes [`LocalKey::try_with`]: https://doc.rust-lang.org/std/thread/struct.LocalKey.html#method.try_with [`Option::cloned`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.cloned [`btree_map::Entry::and_modify`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.and_modify -[`convert::TryFrom`]: https://doc.rust-lang.org/std/convert/trait.TryFrom.html -[`convert::TryInto`]: https://doc.rust-lang.org/std/convert/trait.TryInto.html [`fs::read_to_string`]: https://doc.rust-lang.org/std/fs/fn.read_to_string.html [`fs::read`]: https://doc.rust-lang.org/std/fs/fn.read.html [`fs::write`]: https://doc.rust-lang.org/std/fs/fn.write.html From 31a8ffec713ea552e239eb36c742aa12e809e469 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Mon, 7 May 2018 15:44:28 +0100 Subject: [PATCH 09/18] Added regression function match value test, closes #44333 --- src/test/run-pass/issue-44333.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/test/run-pass/issue-44333.rs diff --git a/src/test/run-pass/issue-44333.rs b/src/test/run-pass/issue-44333.rs new file mode 100644 index 0000000000000..72731f4132113 --- /dev/null +++ b/src/test/run-pass/issue-44333.rs @@ -0,0 +1,29 @@ +// 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. + +type Func = fn(usize, usize) -> usize; + +fn foo(a: usize, b: usize) -> usize { a + b } +fn bar(a: usize, b: usize) -> usize { a * b } +fn test(x: usize) -> Func { + if x % 2 == 0 { foo } + else { bar } +} + +const FOO: Func = foo; +const BAR: Func = bar; + +fn main() { + match test(std::env::consts::ARCH.len()) { + FOO => println!("foo"), + BAR => println!("bar"), + _ => unreachable!(), + } +} From 1abed9cebf27f1f68e8711cb15ba9c2587b4da68 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 7 May 2018 09:18:12 -0700 Subject: [PATCH 10/18] Add explanation for #[must_use] on Result --- src/libcore/result.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index c152d4979b90e..e0cc669d0350a 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -251,7 +251,7 @@ use ops; /// [`Ok`]: enum.Result.html#variant.Ok /// [`Err`]: enum.Result.html#variant.Err #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] -#[must_use] +#[must_use = "this `Result` may be an `Err` variant, which should be handled"] #[stable(feature = "rust1", since = "1.0.0")] pub enum Result { /// Contains the success value From 6e49c837f614a8670a5773428b4934eb280bca61 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 7 May 2018 09:26:03 -0700 Subject: [PATCH 11/18] Add explanation for #[must_use] on Debug builders --- src/libcore/fmt/builders.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index a1f4c6995dae0..e8ea2e743da93 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -84,7 +84,7 @@ impl<'a> fmt::Write for PadAdapter<'a> { /// // prints "Foo { bar: 10, baz: "Hello World" }" /// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }); /// ``` -#[must_use] +#[must_use = "must eventually call `finish()` on Debug builders"] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] pub struct DebugStruct<'a, 'b: 'a> { @@ -181,7 +181,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// // prints "Foo(10, "Hello World")" /// println!("{:?}", Foo(10, "Hello World".to_string())); /// ``` -#[must_use] +#[must_use = "must eventually call `finish()` on Debug builders"] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] pub struct DebugTuple<'a, 'b: 'a> { @@ -319,7 +319,7 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { /// // prints "{10, 11}" /// println!("{:?}", Foo(vec![10, 11])); /// ``` -#[must_use] +#[must_use = "must eventually call `finish()` on Debug builders"] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] pub struct DebugSet<'a, 'b: 'a> { @@ -390,7 +390,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// // prints "[10, 11]" /// println!("{:?}", Foo(vec![10, 11])); /// ``` -#[must_use] +#[must_use = "must eventually call `finish()` on Debug builders"] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] pub struct DebugList<'a, 'b: 'a> { @@ -461,7 +461,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// // prints "{"A": 10, "B": 11}" /// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])); /// ``` -#[must_use] +#[must_use = "must eventually call `finish()` on Debug builders"] #[allow(missing_debug_implementations)] #[stable(feature = "debug_builders", since = "1.2.0")] pub struct DebugMap<'a, 'b: 'a> { From f8b774fbf1f57e520b58ae3828e4b3a1ddf1d97c Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 7 May 2018 09:27:50 -0700 Subject: [PATCH 12/18] Add explanation for #[must_use] on mutex guards --- src/libstd/sync/mutex.rs | 2 +- src/libstd/sync/rwlock.rs | 4 ++-- src/libstd/sys_common/remutex.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 3b4904c98e871..f3503b0b3a6a7 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -150,7 +150,7 @@ unsafe impl Sync for Mutex { } /// [`lock`]: struct.Mutex.html#method.lock /// [`try_lock`]: struct.Mutex.html#method.try_lock /// [`Mutex`]: struct.Mutex.html -#[must_use] +#[must_use = "if unused the Mutex will immediately unlock"] #[stable(feature = "rust1", since = "1.0.0")] pub struct MutexGuard<'a, T: ?Sized + 'a> { // funny underscores due to how Deref/DerefMut currently work (they diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index f7fdedc0d2179..e3db60cff8474 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -94,7 +94,7 @@ unsafe impl Sync for RwLock {} /// [`read`]: struct.RwLock.html#method.read /// [`try_read`]: struct.RwLock.html#method.try_read /// [`RwLock`]: struct.RwLock.html -#[must_use] +#[must_use = "if unused the RwLock will immediately unlock"] #[stable(feature = "rust1", since = "1.0.0")] pub struct RwLockReadGuard<'a, T: ?Sized + 'a> { __lock: &'a RwLock, @@ -115,7 +115,7 @@ unsafe impl<'a, T: ?Sized + Sync> Sync for RwLockReadGuard<'a, T> {} /// [`write`]: struct.RwLock.html#method.write /// [`try_write`]: struct.RwLock.html#method.try_write /// [`RwLock`]: struct.RwLock.html -#[must_use] +#[must_use = "if unused the RwLock will immediately unlock"] #[stable(feature = "rust1", since = "1.0.0")] pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> { __lock: &'a RwLock, diff --git a/src/libstd/sys_common/remutex.rs b/src/libstd/sys_common/remutex.rs index ce43ec6d9abf5..022056f8a8a70 100644 --- a/src/libstd/sys_common/remutex.rs +++ b/src/libstd/sys_common/remutex.rs @@ -41,7 +41,7 @@ unsafe impl Sync for ReentrantMutex {} /// because implementation of the trait would violate Rust’s reference aliasing /// rules. Use interior mutability (usually `RefCell`) in order to mutate the /// guarded data. -#[must_use] +#[must_use = "if unused the ReentrantMutex will immediately unlock"] pub struct ReentrantMutexGuard<'a, T: 'a> { // funny underscores due to how Deref currently works (it disregards field // privacy). From a72a0801bdab22d7c0167f67d1148276ea874d2e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 7 May 2018 09:30:11 -0700 Subject: [PATCH 13/18] Add explanation for #[must_use] on string replace methods --- src/liballoc/str.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 0cbe65db53cad..9e693c89be90d 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -207,7 +207,8 @@ impl str { /// let s = "this is old"; /// assert_eq!(s, s.replace("cookie monster", "little lamb")); /// ``` - #[must_use] + #[must_use = "this returns the replaced string as a new allocation, \ + without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn replace<'a, P: Pattern<'a>>(&'a self, from: P, to: &str) -> String { @@ -247,7 +248,8 @@ impl str { /// let s = "this is old"; /// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10)); /// ``` - #[must_use] + #[must_use = "this returns the replaced string as a new allocation, \ + without modifying the original"] #[stable(feature = "str_replacen", since = "1.16.0")] pub fn replacen<'a, P: Pattern<'a>>(&'a self, pat: P, to: &str, count: usize) -> String { // Hope to reduce the times of re-allocation From 663c0961b9e72301ab5400f3aa066acf20586268 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Tue, 8 May 2018 17:07:24 +0900 Subject: [PATCH 14/18] Cleanup a `use` in a raw_vec test `allocator` is deprecated in favor of `alloc`, and `Alloc` is already imported through `super::*`. --- src/liballoc/raw_vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index eb25ae1751170..4d73d3aa07e66 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -748,7 +748,7 @@ mod tests { #[test] fn allocator_param() { - use allocator::{Alloc, AllocErr}; + use alloc::AllocErr; // Writing a test of integration between third-party // allocators and RawVec is a little tricky because the RawVec From 576aab9dfe313a452ad0f3465d8a2e83f00b0884 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 4 May 2018 22:27:29 -0700 Subject: [PATCH 15/18] Update the Cargo/stdsimd submodules Hopefully brining in a few fixes to Cargo regressions as well as some new stdsimd functions! --- src/stdsimd | 2 +- src/tools/cargo | 2 +- src/tools/rls | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/stdsimd b/src/stdsimd index 1ea18a5cb431e..2f86c75a2479c 160000 --- a/src/stdsimd +++ b/src/stdsimd @@ -1 +1 @@ -Subproject commit 1ea18a5cb431e24aa838b652ac305acc5e394d6b +Subproject commit 2f86c75a2479cf051b92fc98273daaf7f151e7a1 diff --git a/src/tools/cargo b/src/tools/cargo index af3f1cd29bc87..9e53ac6e6525d 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit af3f1cd29bc872b932a13083e531255aab233a7e +Subproject commit 9e53ac6e6525da914cb05a85e5e8eff7b5dca81f diff --git a/src/tools/rls b/src/tools/rls index 1263f1ff25bb3..d2ade31a52a41 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 1263f1ff25bb329b76f74715ad4a7ec0d1f71430 +Subproject commit d2ade31a52a417257742de72c5936a8a342a34b5 From 23b6e465b9546b99c8b7609bfa4eeaf2094eed09 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Tue, 8 May 2018 12:05:07 -0400 Subject: [PATCH 16/18] Add more logarithm constants --- src/libcore/num/f32.rs | 8 ++++++++ src/libcore/num/f64.rs | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 8d5f6f601daf8..672119eba7f9d 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -128,10 +128,18 @@ pub mod consts { #[stable(feature = "rust1", since = "1.0.0")] pub const LOG2_E: f32 = 1.44269504088896340735992468100189214_f32; + /// log2(10) + #[unstable(feature = "extra_log_consts", issue = "50540")] + pub const LOG2_10: f32 = 3.32192809488736234787031942948939018_f32; + /// log10(e) #[stable(feature = "rust1", since = "1.0.0")] pub const LOG10_E: f32 = 0.434294481903251827651128918916605082_f32; + /// log10(2) + #[unstable(feature = "extra_log_consts", issue = "50540")] + pub const LOG10_2: f32 = 0.301029995663981195213738894724493027_f32; + /// ln(2) #[stable(feature = "rust1", since = "1.0.0")] pub const LN_2: f32 = 0.693147180559945309417232121458176568_f32; diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 08b869734d496..220b23a1e6a01 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -124,10 +124,18 @@ pub mod consts { #[stable(feature = "rust1", since = "1.0.0")] pub const E: f64 = 2.71828182845904523536028747135266250_f64; + /// log2(10) + #[unstable(feature = "extra_log_consts", issue = "50540")] + pub const LOG2_10: f64 = 3.32192809488736234787031942948939018_f64; + /// log2(e) #[stable(feature = "rust1", since = "1.0.0")] pub const LOG2_E: f64 = 1.44269504088896340735992468100189214_f64; + /// log10(2) + #[unstable(feature = "extra_log_consts", issue = "50540")] + pub const LOG10_2: f64 = 0.301029995663981195213738894724493027_f64; + /// log10(e) #[stable(feature = "rust1", since = "1.0.0")] pub const LOG10_E: f64 = 0.434294481903251827651128918916605082_f64; From 65ea0ff29d32ca4fea30477f7fb1a1d43342dc26 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 May 2018 16:53:31 +1000 Subject: [PATCH 17/18] Optimize string handling in lit_token(). In the common case, the string value in a string literal Token is the same as the string value in a string literal LitKind. (The exception is when escapes or \r are involved.) This patch takes advantage of that to avoid calling str_lit() and re-interning the string in that case. This speeds up incremental builds for a few of the rustc-benchmarks, the best by 3%. --- src/libsyntax/parse/mod.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index f252020bc3169..f26a6a5307401 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -419,13 +419,24 @@ pub fn lit_token(lit: token::Lit, suf: Option, diag: Option<(Span, &Hand token::Integer(s) => (false, integer_lit(&s.as_str(), suf, diag)), token::Float(s) => (false, float_lit(&s.as_str(), suf, diag)), - token::Str_(s) => { - let s = Symbol::intern(&str_lit(&s.as_str(), diag)); - (true, Some(LitKind::Str(s, ast::StrStyle::Cooked))) + token::Str_(mut sym) => { + // If there are no characters requiring special treatment we can + // reuse the symbol from the Token. Otherwise, we must generate a + // new symbol because the string in the LitKind is different to the + // string in the Token. + let s = &sym.as_str(); + if s.as_bytes().iter().any(|&c| c == b'\\' || c == b'\r') { + sym = Symbol::intern(&str_lit(s, diag)); + } + (true, Some(LitKind::Str(sym, ast::StrStyle::Cooked))) } - token::StrRaw(s, n) => { - let s = Symbol::intern(&raw_str_lit(&s.as_str())); - (true, Some(LitKind::Str(s, ast::StrStyle::Raw(n)))) + token::StrRaw(mut sym, n) => { + // Ditto. + let s = &sym.as_str(); + if s.contains('\r') { + sym = Symbol::intern(&raw_str_lit(s)); + } + (true, Some(LitKind::Str(sym, ast::StrStyle::Raw(n)))) } token::ByteStr(i) => { (true, Some(LitKind::ByteStr(byte_str_lit(&i.as_str())))) From 111786d30e346f356e87d5ec4e6da218d66a85e2 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Wed, 9 May 2018 11:06:20 +0100 Subject: [PATCH 18/18] Update RELEASES.md --- RELEASES.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index ba9950e57c865..26dd5a5c7f637 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -8,14 +8,14 @@ Language - [The inclusive range syntax e.g. `for x in 0..=10` is now stable.][47813] - [Stablise `'_`. The underscore lifetime can be used anywhere where a lifetime can be elided.][49458] -- [`impl Trait` is now stable allowing you to have abstract - return types.][49255] e.g. `fn foo() -> impl Iterator` or +- [`impl Trait` is now stable allowing you to have abstract types in returns + or in function parameters.][49255] e.g. `fn foo() -> impl Iterator` or `fn open(path: impl AsRef)`. - [Pattern matching will now automatically apply dereferences.][49394] - [128-bit integers in the form of `u128` and `i128` are now stable.][49101] - [`main` can now return `Result<(), E: Debug>`][49162] in addition to `()`. - [A lot of operations are now available in a const context.][46882] E.g. You - can now index into constant arrays, reference and deference into constants, + can now index into constant arrays, reference and dereference into constants, and use Tuple struct constructors. - [Fixed entry slice patterns are now stable.][48516] e.g. ```rust @@ -125,6 +125,7 @@ Compatibility Notes - [`".e0"` will now no longer parse as `0.0` and will instead cause an error.][48235] - [Removed hoedown from rustdoc.][48274] +- [Bounds on higher-kinded lifetimes a hard error.][48326] [46882]: https://github.com/rust-lang/rust/pull/46882 [47379]: https://github.com/rust-lang/rust/pull/47379 @@ -137,6 +138,7 @@ Compatibility Notes [48274]: https://github.com/rust-lang/rust/pull/48274 [48281]: https://github.com/rust-lang/rust/pull/48281 [48296]: https://github.com/rust-lang/rust/pull/48296 +[48326]: https://github.com/rust-lang/rust/pull/48326 [48359]: https://github.com/rust-lang/rust/pull/48359 [48404]: https://github.com/rust-lang/rust/pull/48404 [48481]: https://github.com/rust-lang/rust/pull/48481