From bf90d4377f046b7809a50b8fa74be6848d4c1a86 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Fri, 22 Jun 2018 21:23:17 +0100 Subject: [PATCH 01/14] Updated RELEASES for 1.28.0 --- RELEASES.md | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 068e9e7263e7d..1dee94b76ac31 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,141 @@ +Version 1.28.0 (2018-08-02) +=========================== + +Language +-------- +- [Stabilised the `#[repr(transparent)]` attribute.][51562] This attribute + allows a Rust newtype wrapper (`struct NewType(T);`) to be represented as + the inner type across Foreign Function Interface (FFI) boundaries. +- [The keywords `pure`, `sizeof`, `alignof`, and `offsetof` have been unreserved + and can now be used as identifiers.][51196] +- [Stabilised the `GlobalAlloc` trait and `#[global_allocator]` + attribute.][51241] This will allow users to specify a global allocator for + their program. +- [Unit test functions marked with the `#[test]` attribute can now return + `Result<(), E: Debug>` in addition to `()`.][51298] +- [Stabilised a `lifetime` specifier to `macro_rules!` allowing macros to easily + target lifetimes.][50385] + +Compiler +-------- +- [Stabilised the `s` and `z` optimisation levels.][50265] These optimisations + prioritise making smaller binary sizes. `z` is the same as `s` with the + exception that it does not vectorise loops, which typically results in an even + smaller binary. +- [Stabilised the short error format.][49546] Specified with + `--error-format=short` this option will provide a more compressed output of + rust error messages. +- [Added a lint warning when you have duplicated `macro_export`s.][50143] +- [Reduced the number of allocations in the macro parser.][50855] This can + improve compile times of macro heavy crates on average by 5%. + +Libraries +--------- +- [Implemented `Default` for `&mut str`.][51306] +- [Implemented `From` for all integer and unsigned number types.][50554] +- [Implemented `Extend` for `()`.][50234] +- [The `Debug` implementation of `time::Duration` should now be more easily + human readable.][50364] Previously a `Duration` of one second would printed as + `Duration { secs: 1, nanos: 0 }` will now be printed as `1s`. +- [Implemented `From<&String>` for `Cow`, `From<&Vec>` for `Cow<[T]>`, + `From>` for `CString`, `From, From, From<&CString>` + for `Cow`, `From, From, From<&OsString>` for + `Cow`, `From<&PathBuf>` for `Cow`, and `From>` + for `PathBuf`.][50170] +- [`DirEntry::metadata` now uses `fstatat` instead of `lstat` when + possible.][51050] This can provide up to a 40% speed increase. +- [Improved error messages when using `format!`.][50610] + +Stabilized APIs +--------------- +- [`Iterator::step_by`] +- [`Path::ancestors`] +- [`btree_map::Entry::or_default`] +- [`fmt::Alignment`] +- [`hash_map::Entry::or_default`] +- [`iter::repeat_with`] +- [`num::NonZeroU128`] +- [`num::NonZeroU16`] +- [`num::NonZeroU32`] +- [`num::NonZeroU64`] +- [`num::NonZeroU8`] +- [`ops::RangeBounds`] +- [`slice::SliceIndex`] +- [`slice::from_mut`] +- [`slice::from_ref`] +- [`{Any + Send + Sync}::downcast_mut`] +- [`{Any + Send + Sync}::downcast_ref`] +- [`{Any + Send + Sync}::is`] + +Cargo +----- +- [Cargo will now no longer allow you to publish crates with build scripts that + modify the `src` directory.][5584] The `src` directory in a crate should be + considered to be immutable. + +Misc +---- +- [Stabilised the `suggestion_applicability` field in the json output.][50486] + This will allow dev tools to check whether a code suggestion would apply + to them. + +Compatibility Notes +------------------- +- [Rust will no longer consider trait objects with duplicated constraints to + have implementations.][51276] For example the below code will now fail + to compile. + ```rust + trait Trait {} + + impl Trait + Send { + fn test(&self) { println!("one"); } //~ ERROR duplicate definitions with name `test` + } + + impl Trait + Send + Send { + fn test(&self) { println!("two"); } + } + ``` + +[49546]: https://github.com/rust-lang/rust/pull/49546/ +[50143]: https://github.com/rust-lang/rust/pull/50143/ +[50170]: https://github.com/rust-lang/rust/pull/50170/ +[50234]: https://github.com/rust-lang/rust/pull/50234/ +[50265]: https://github.com/rust-lang/rust/pull/50265/ +[50364]: https://github.com/rust-lang/rust/pull/50364/ +[50385]: https://github.com/rust-lang/rust/pull/50385/ +[50486]: https://github.com/rust-lang/rust/pull/50486/ +[50554]: https://github.com/rust-lang/rust/pull/50554/ +[50610]: https://github.com/rust-lang/rust/pull/50610/ +[50855]: https://github.com/rust-lang/rust/pull/50855/ +[51050]: https://github.com/rust-lang/rust/pull/51050/ +[51196]: https://github.com/rust-lang/rust/pull/51196/ +[51200]: https://github.com/rust-lang/rust/pull/51200/ +[51241]: https://github.com/rust-lang/rust/pull/51241/ +[51276]: https://github.com/rust-lang/rust/pull/51276/ +[51298]: https://github.com/rust-lang/rust/pull/51298/ +[51306]: https://github.com/rust-lang/rust/pull/51306/ +[51562]: https://github.com/rust-lang/rust/pull/51562/ +[5584]: https://github.com/rust-lang/cargo/pull/5584/ +[`Iterator::step_by`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.step_by +[`Path::ancestors`]: https://doc.rust-lang.org/std/path/struct.Path.html#method.ancestors +[`btree_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.or_default +[`fmt::Alignment`]: https://doc.rust-lang.org/std/fmt/enum.Alignment.html +[`hash_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.or_default +[`iter::repeat_with`]: https://doc.rust-lang.org/std/iter/fn.repeat_with.html +[`num::NonZeroU128`]: https://doc.rust-lang.org/std/num/struct.NonZeroU128.html +[`num::NonZeroU16`]: https://doc.rust-lang.org/std/num/struct.NonZeroU16.html +[`num::NonZeroU32`]: https://doc.rust-lang.org/std/num/struct.NonZeroU32.html +[`num::NonZeroU64`]: https://doc.rust-lang.org/std/num/struct.NonZeroU64.html +[`num::NonZeroU8`]: https://doc.rust-lang.org/std/num/struct.NonZeroU8.html +[`ops::RangeBounds`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html +[`slice::SliceIndex`]: https://doc.rust-lang.org/std/slice/trait.SliceIndex.html +[`slice::from_mut`]: https://doc.rust-lang.org/std/slice/fn.from_mut.html +[`slice::from_ref`]: https://doc.rust-lang.org/std/slice/fn.from_ref.html +[`{Any + Send + Sync}::downcast_mut`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.downcast_mut-2 +[`{Any + Send + Sync}::downcast_ref`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.downcast_ref-2 +[`{Any + Send + Sync}::is`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.is-2 + + Version 1.27.0 (2018-06-21) ========================== From b58047681bd9255905feff26a53f0279e3f533e3 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Fri, 22 Jun 2018 22:36:01 +0100 Subject: [PATCH 02/14] Update RELEASES.md --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 1dee94b76ac31..9118dcd32100f 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -36,7 +36,7 @@ Libraries - [Implemented `Extend` for `()`.][50234] - [The `Debug` implementation of `time::Duration` should now be more easily human readable.][50364] Previously a `Duration` of one second would printed as - `Duration { secs: 1, nanos: 0 }` will now be printed as `1s`. + `Duration { secs: 1, nanos: 0 }` and will now be printed as `1s`. - [Implemented `From<&String>` for `Cow`, `From<&Vec>` for `Cow<[T]>`, `From>` for `CString`, `From, From, From<&CString>` for `Cow`, `From, From, From<&OsString>` for From ffc733fcef4e724524a705c7bc8c9e068fa3ca3a Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Sat, 23 Jun 2018 10:45:46 +0100 Subject: [PATCH 03/14] Update RELEASES.md --- RELEASES.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 9118dcd32100f..fe74e244623f3 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -42,6 +42,8 @@ Libraries for `Cow`, `From, From, From<&OsString>` for `Cow`, `From<&PathBuf>` for `Cow`, and `From>` for `PathBuf`.][50170] +- [Implemented `Shl` and `Shr` for `Wrapping` + and `Wrapping`.][50465] - [`DirEntry::metadata` now uses `fstatat` instead of `lstat` when possible.][51050] This can provide up to a 40% speed increase. - [Improved error messages when using `format!`.][50610] @@ -70,7 +72,7 @@ Stabilized APIs Cargo ----- - [Cargo will now no longer allow you to publish crates with build scripts that - modify the `src` directory.][5584] The `src` directory in a crate should be + modify the `src` directory.][cargo/5584] The `src` directory in a crate should be considered to be immutable. Misc @@ -103,6 +105,7 @@ Compatibility Notes [50265]: https://github.com/rust-lang/rust/pull/50265/ [50364]: https://github.com/rust-lang/rust/pull/50364/ [50385]: https://github.com/rust-lang/rust/pull/50385/ +[50465]: https://github.com/rust-lang/rust/pull/50465/ [50486]: https://github.com/rust-lang/rust/pull/50486/ [50554]: https://github.com/rust-lang/rust/pull/50554/ [50610]: https://github.com/rust-lang/rust/pull/50610/ @@ -115,7 +118,7 @@ Compatibility Notes [51298]: https://github.com/rust-lang/rust/pull/51298/ [51306]: https://github.com/rust-lang/rust/pull/51306/ [51562]: https://github.com/rust-lang/rust/pull/51562/ -[5584]: https://github.com/rust-lang/cargo/pull/5584/ +[cargo/5584]: https://github.com/rust-lang/cargo/pull/5584/ [`Iterator::step_by`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.step_by [`Path::ancestors`]: https://doc.rust-lang.org/std/path/struct.Path.html#method.ancestors [`btree_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.or_default From 3f31c389c491e6082ff850ae6873b3a5097d4d7f Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Tue, 26 Jun 2018 13:41:32 +0100 Subject: [PATCH 04/14] Updated RELEASES --- RELEASES.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index fe74e244623f3..4405b593b29bc 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -3,26 +3,26 @@ Version 1.28.0 (2018-08-02) Language -------- -- [Stabilised the `#[repr(transparent)]` attribute.][51562] This attribute +- [The `#[repr(transparent)]` attribute is now stable.][51562] This attribute allows a Rust newtype wrapper (`struct NewType(T);`) to be represented as the inner type across Foreign Function Interface (FFI) boundaries. - [The keywords `pure`, `sizeof`, `alignof`, and `offsetof` have been unreserved and can now be used as identifiers.][51196] -- [Stabilised the `GlobalAlloc` trait and `#[global_allocator]` - attribute.][51241] This will allow users to specify a global allocator for +- [The `GlobalAlloc` trait and `#[global_allocator]` attribute are now + stable.][51241] This will allow users to specify a global allocator for their program. - [Unit test functions marked with the `#[test]` attribute can now return `Result<(), E: Debug>` in addition to `()`.][51298] -- [Stabilised a `lifetime` specifier to `macro_rules!` allowing macros to easily - target lifetimes.][50385] +- [The `lifetime` specifier for `macro_rules!` is now stable.][50385] This + allows macros to easily target lifetimes. Compiler -------- -- [Stabilised the `s` and `z` optimisation levels.][50265] These optimisations +- [The `s` and `z` optimisation levels are now stable.][50265] These optimisations prioritise making smaller binary sizes. `z` is the same as `s` with the exception that it does not vectorise loops, which typically results in an even smaller binary. -- [Stabilised the short error format.][49546] Specified with +- [The short error format is now stable.][49546] Specified with `--error-format=short` this option will provide a more compressed output of rust error messages. - [Added a lint warning when you have duplicated `macro_export`s.][50143] @@ -77,9 +77,9 @@ Cargo Misc ---- -- [Stabilised the `suggestion_applicability` field in the json output.][50486] - This will allow dev tools to check whether a code suggestion would apply - to them. +- [The `suggestion_applicability` field in `rustc`'s json output is now + stable.][50486] This will allow dev tools to check whether a code suggestion + would apply to them. Compatibility Notes ------------------- @@ -328,7 +328,7 @@ 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 +- [The `'_` lifetime is now stable. The underscore lifetime can be used anywhere where a lifetime can be elided.][49458] - [`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 @@ -529,7 +529,7 @@ Version 1.25.0 (2018-03-29) Language -------- -- [Stabilised `#[repr(align(x))]`.][47006] [RFC 1358] +- [The `#[repr(align(x))]` attribute is now stable.][47006] [RFC 1358] - [You can now use nested groups of imports.][47948] e.g. `use std::{fs::File, io::Read, path::{Path, PathBuf}};` - [You can now have `|` at the start of a match arm.][47947] e.g. From dab257f1932718b659564a242ee450016175d12c Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Wed, 4 Jul 2018 15:56:18 +0100 Subject: [PATCH 05/14] Update RELEASES.md --- RELEASES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 4405b593b29bc..e7887f7e5ec74 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -56,6 +56,7 @@ Stabilized APIs - [`fmt::Alignment`] - [`hash_map::Entry::or_default`] - [`iter::repeat_with`] +- [`num::NonZeroUsize`] - [`num::NonZeroU128`] - [`num::NonZeroU16`] - [`num::NonZeroU32`] @@ -125,6 +126,7 @@ Compatibility Notes [`fmt::Alignment`]: https://doc.rust-lang.org/std/fmt/enum.Alignment.html [`hash_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.or_default [`iter::repeat_with`]: https://doc.rust-lang.org/std/iter/fn.repeat_with.html +[`num::NonZeroUsize`]: https://doc.rust-lang.org/std/num/struct.NonZeroUsize.html [`num::NonZeroU128`]: https://doc.rust-lang.org/std/num/struct.NonZeroU128.html [`num::NonZeroU16`]: https://doc.rust-lang.org/std/num/struct.NonZeroU16.html [`num::NonZeroU32`]: https://doc.rust-lang.org/std/num/struct.NonZeroU32.html From dc425e2e64863d4e1aa0f2bb41f7bfa3cd14b558 Mon Sep 17 00:00:00 2001 From: Val Markovic Date: Wed, 4 Jul 2018 17:26:45 -0700 Subject: [PATCH 06/14] Clarifying how the alignment of the struct works The docs were not specifying how to compute the alignment of the struct, so I had to spend some time trying to figure out how that works. Found the answer [on this page](http://camlorn.net/posts/April%202017/rust-struct-field-reordering.html): > The total size of this struct is 5, but the most-aligned field is b with alignment 2, so we round up to 6 and give the struct an alignment of 2 bytes. --- src/libcore/mem.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 84173654655eb..8fb4e0d6a02e3 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -229,6 +229,8 @@ pub fn forget(t: T) { /// 2. Round up the current size to the nearest multiple of the next field's [alignment]. /// /// Finally, round the size of the struct to the nearest multiple of its [alignment]. +/// The alignment of the struct is usually the largest alignment of all its +/// fields; this can be changed with the use of `repr(align(N))`. /// /// Unlike `C`, zero sized structs are not rounded up to one byte in size. /// @@ -283,7 +285,8 @@ pub fn forget(t: T) { /// // The size of the second field is 2, so add 2 to the size. Size is 4. /// // The alignment of the third field is 1, so add 0 to the size for padding. Size is 4. /// // The size of the third field is 1, so add 1 to the size. Size is 5. -/// // Finally, the alignment of the struct is 2, so add 1 to the size for padding. Size is 6. +/// // Finally, the alignment of the struct is 2 (because the largest alignment amongst its +/// // fields is 2), so add 1 to the size for padding. Size is 6. /// assert_eq!(6, mem::size_of::()); /// /// #[repr(C)] From e769deca998479c7b78931af45a26c6c822c74f7 Mon Sep 17 00:00:00 2001 From: willmo Date: Sat, 7 Jul 2018 20:09:34 -0700 Subject: [PATCH 07/14] Add #[repr(transparent)] to Atomic* types This allows them to be used in #[repr(C)] structs without warnings. Since rust-lang/rfcs#1649 and rust-lang/rust#35603 they are already documented to have "the same in-memory representation as" their corresponding primitive types. This just makes that explicit. --- src/libcore/sync/atomic.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index e9d1fb8911504..1e2b18bf9b038 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -124,6 +124,7 @@ pub fn spin_loop_hint() { /// [`bool`]: ../../../std/primitive.bool.html #[cfg(target_has_atomic = "8")] #[stable(feature = "rust1", since = "1.0.0")] +#[repr(transparent)] pub struct AtomicBool { v: UnsafeCell, } @@ -147,6 +148,7 @@ unsafe impl Sync for AtomicBool {} /// This type has the same in-memory representation as a `*mut T`. #[cfg(target_has_atomic = "ptr")] #[stable(feature = "rust1", since = "1.0.0")] +#[repr(transparent)] pub struct AtomicPtr { p: UnsafeCell<*mut T>, } @@ -976,6 +978,7 @@ macro_rules! atomic_int { /// /// [module-level documentation]: index.html #[$stable] + #[repr(transparent)] pub struct $atomic_type { v: UnsafeCell<$int_type>, } From dda75249e5fee128f67c5ff9763cb0fc022b7403 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sun, 8 Jul 2018 18:27:19 +0100 Subject: [PATCH 08/14] Copy libgcc as well after building musl This is needed for rust-lang/libc#1034. --- src/ci/docker/scripts/musl.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ci/docker/scripts/musl.sh b/src/ci/docker/scripts/musl.sh index f87ba8fe4e60e..ae908f639872f 100644 --- a/src/ci/docker/scripts/musl.sh +++ b/src/ci/docker/scripts/musl.sh @@ -72,3 +72,6 @@ cmake ../libunwind-release_$LLVM \ hide_output make -j$(nproc) cp lib/libunwind.a /musl-$TAG/lib cd ../ && rm -rf libunwind-build + +# Copy libgcc since musl may depend on symbols defined in it +cp $($CC $CFLAGS -print-libgcc-file-name) /musl-$TAG/lib From 23717822a31c7d4436528718cd0f4c0bbad64ff5 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Sun, 8 Jul 2018 18:02:33 -0400 Subject: [PATCH 09/14] use proper footnote syntax for references The previous syntax was causing rustdoc to interpret them as links. --- src/libcore/num/flt2dec/strategy/dragon.rs | 11 +++++------ src/libcore/num/flt2dec/strategy/grisu.rs | 13 ++++++------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/libcore/num/flt2dec/strategy/dragon.rs b/src/libcore/num/flt2dec/strategy/dragon.rs index 6aa4f297e75ba..aa6a08cb2057e 100644 --- a/src/libcore/num/flt2dec/strategy/dragon.rs +++ b/src/libcore/num/flt2dec/strategy/dragon.rs @@ -8,12 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -Almost direct (but slightly optimized) Rust translation of Figure 3 of [1]. - -[1] Burger, R. G. and Dybvig, R. K. 1996. Printing floating-point numbers - quickly and accurately. SIGPLAN Not. 31, 5 (May. 1996), 108-116. -*/ +//! Almost direct (but slightly optimized) Rust translation of Figure 3 of "Printing +//! Floating-Point Numbers Quickly and Accurately"[^1]. +//! +//! [^1]: Burger, R. G. and Dybvig, R. K. 1996. Printing floating-point numbers +//! quickly and accurately. SIGPLAN Not. 31, 5 (May. 1996), 108-116. use cmp::Ordering; diff --git a/src/libcore/num/flt2dec/strategy/grisu.rs b/src/libcore/num/flt2dec/strategy/grisu.rs index cf70a1978f5e6..f33186e59c2e6 100644 --- a/src/libcore/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/num/flt2dec/strategy/grisu.rs @@ -8,13 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -Rust adaptation of Grisu3 algorithm described in [1]. It uses about -1KB of precomputed table, and in turn, it's very quick for most inputs. - -[1] Florian Loitsch. 2010. Printing floating-point numbers quickly and - accurately with integers. SIGPLAN Not. 45, 6 (June 2010), 233-243. -*/ +//! Rust adaptation of the Grisu3 algorithm described in "Printing Floating-Point Numbers Quickly +//! and Accurately with Integers"[^1]. It uses about 1KB of precomputed table, and in turn, it's +//! very quick for most inputs. +//! +//! [^1]: Florian Loitsch. 2010. Printing floating-point numbers quickly and +//! accurately with integers. SIGPLAN Not. 45, 6 (June 2010), 233-243. use num::diy_float::Fp; use num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up}; From a6adb1ebff51dd4ff2e724bf980c9b8586142beb Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 7 Jul 2018 19:53:52 -0400 Subject: [PATCH 10/14] find and highlight the `&` or `'_` in `region_name` --- src/librustc/hir/mod.rs | 9 + .../error_reporting/region_name.rs | 294 +++++++++++++++++- src/libsyntax/codemap.rs | 9 + src/test/ui/borrowck/issue-7573.nll.stderr | 2 +- .../expect-region-supply-region.nll.stderr | 4 +- .../static-return-lifetime-infered.nll.stderr | 2 +- .../dyn-trait-underscore.nll.stderr | 2 +- 7 files changed, 300 insertions(+), 22 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 8d83dd3279c64..f18846b8574df 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -402,6 +402,15 @@ pub enum GenericArg { Type(Ty), } +impl GenericArg { + pub fn span(&self) -> Span { + match self { + GenericArg::Lifetime(l) => l.span, + GenericArg::Type(t) => t.span, + } + } +} + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct GenericArgs { /// The generic arguments for this path segment. diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index bf8c9c8c3bef4..16dec2725ff04 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -10,9 +10,11 @@ use borrow_check::nll::region_infer::RegionInferenceContext; use borrow_check::nll::ToRegionVid; +use rustc::hir; use rustc::hir::def_id::DefId; use rustc::mir::{Local, Mir}; -use rustc::ty::{self, RegionVid, TyCtxt}; +use rustc::ty::subst::{Substs, UnpackedKind}; +use rustc::ty::{self, RegionVid, Ty, TyCtxt}; use rustc_data_structures::indexed_vec::Idx; use rustc_errors::DiagnosticBuilder; use syntax::ast::Name; @@ -60,7 +62,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.give_name_from_error_region(tcx, mir_def_id, fr, counter, diag) .or_else(|| { - self.give_name_if_anonymous_region_appears_in_arguments(tcx, mir, fr, counter, diag) + self.give_name_if_anonymous_region_appears_in_arguments( + tcx, mir, mir_def_id, fr, counter, diag, + ) }) .or_else(|| { self.give_name_if_anonymous_region_appears_in_upvars(tcx, mir, fr, counter, diag) @@ -129,20 +133,24 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>, + mir_def_id: DefId, fr: RegionVid, counter: &mut usize, diag: &mut DiagnosticBuilder<'_>, ) -> Option { let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs(); - let argument_index = self.universal_regions + let argument_index = self + .universal_regions .unnormalized_input_tys .iter() .skip(implicit_inputs) .position(|arg_ty| { - debug!("give_name_if_anonymous_region_appears_in_arguments: arg_ty = {:?}", arg_ty); + debug!( + "give_name_if_anonymous_region_appears_in_arguments: arg_ty = {:?}", + arg_ty + ); tcx.any_free_region_meets(arg_ty, |r| r.to_region_vid() == fr) - })? - + implicit_inputs; + })?; debug!( "give_name_if_anonymous_region_appears_in_arguments: \ @@ -150,9 +158,23 @@ impl<'tcx> RegionInferenceContext<'tcx> { fr, argument_index, self.universal_regions.unnormalized_input_tys[argument_index], ); + let arg_ty = + self.universal_regions.unnormalized_input_tys[implicit_inputs + argument_index]; + if let Some(region_name) = self.give_name_if_we_can_match_hir_ty_from_argument( + tcx, + mir_def_id, + fr, + arg_ty, + argument_index, + counter, + diag, + ) { + return Some(region_name); + } + let region_name = self.synthesize_region_name(counter); - let argument_local = Local::new(argument_index + 1); + let argument_local = Local::new(argument_index + implicit_inputs + 1); let argument_span = mir.local_decls[argument_local].source_info.span; diag.span_label( argument_span, @@ -162,6 +184,240 @@ impl<'tcx> RegionInferenceContext<'tcx> { Some(region_name) } + fn give_name_if_we_can_match_hir_ty_from_argument( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + mir_def_id: DefId, + needle_fr: RegionVid, + argument_ty: Ty<'tcx>, + argument_index: usize, + counter: &mut usize, + diag: &mut DiagnosticBuilder<'_>, + ) -> Option { + let mir_node_id = tcx.hir.as_local_node_id(mir_def_id)?; + let fn_decl = tcx.hir.fn_decl(mir_node_id)?; + let argument_hir_ty: &hir::Ty = &fn_decl.inputs[argument_index]; + match argument_hir_ty.node { + // This indicates a variable with no type annotation, like + // `|x|`... in that case, we can't highlight the type but + // must highlight the variable. + hir::TyInfer => None, + + _ => self.give_name_if_we_can_match_hir_ty( + tcx, + needle_fr, + argument_ty, + argument_hir_ty, + counter, + diag, + ), + } + } + + /// Attempts to highlight the specific part of a type annotation + /// that contains the anonymous reference we want to give a name + /// to. For example, we might produce an annotation like this: + /// + /// ``` + /// | fn a(items: &[T]) -> Box> { + /// | - let's call the lifetime of this reference `'1` + /// ``` + /// + /// the way this works is that we match up `argument_ty`, which is + /// a `Ty<'tcx>` (the internal form of the type) with + /// `argument_hir_ty`, a `hir::Ty` (the syntax of the type + /// annotation). We are descending through the types stepwise, + /// looking in to find the region `needle_fr` in the internal + /// type. Once we find that, we can use the span of the `hir::Ty` + /// to add the highlight. + /// + /// This is a somewhat imperfect process, so long the way we also + /// keep track of the **closest** type we've found. If we fail to + /// find the exact `&` or `'_` to highlight, then we may fall back + /// to highlighting that closest type instead. + fn give_name_if_we_can_match_hir_ty( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + needle_fr: RegionVid, + argument_ty: Ty<'tcx>, + argument_hir_ty: &hir::Ty, + counter: &mut usize, + diag: &mut DiagnosticBuilder<'_>, + ) -> Option { + let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty)> = &mut Vec::new(); + + search_stack.push((argument_ty, argument_hir_ty)); + + let mut closest_match: &hir::Ty = argument_hir_ty; + + while let Some((ty, hir_ty)) = search_stack.pop() { + // While we search, also track the closet match. + if tcx.any_free_region_meets(&ty, |r| r.to_region_vid() == needle_fr) { + closest_match = hir_ty; + } + + match (&ty.sty, &hir_ty.node) { + // Check if the `argument_ty` is `&'X ..` where `'X` + // is the region we are looking for -- if so, and we have a `&T` + // on the RHS, then we want to highlight the `&` like so: + // + // & + // - let's call the lifetime of this reference `'1` + (ty::TyRef(region, referent_ty, _), hir::TyRptr(_lifetime, referent_hir_ty)) => { + if region.to_region_vid() == needle_fr { + let region_name = self.synthesize_region_name(counter); + + // Just grab the first character, the `&`. + let codemap = tcx.sess.codemap(); + let ampersand_span = codemap.start_point(hir_ty.span); + + diag.span_label( + ampersand_span, + format!( + "let's call the lifetime of this reference `{}`", + region_name + ), + ); + + return Some(region_name); + } + + // Otherwise, let's descend into the referent types. + search_stack.push((referent_ty, &referent_hir_ty.ty)); + } + + // Match up something like `Foo<'1>` + (ty::TyAdt(_adt_def, substs), hir::TyPath(hir::QPath::Resolved(None, path))) => { + if let Some(last_segment) = path.segments.last() { + if let Some(name) = self.match_adt_and_segment( + substs, + needle_fr, + last_segment, + counter, + diag, + search_stack, + ) { + return Some(name); + } + } + } + + // The following cases don't have lifetimes, so we + // just worry about trying to match up the rustc type + // with the HIR types: + (ty::TyTuple(elem_tys), hir::TyTup(elem_hir_tys)) => { + search_stack.extend(elem_tys.iter().cloned().zip(elem_hir_tys)); + } + + (ty::TySlice(elem_ty), hir::TySlice(elem_hir_ty)) + | (ty::TyArray(elem_ty, _), hir::TyArray(elem_hir_ty, _)) => { + search_stack.push((elem_ty, elem_hir_ty)); + } + + (ty::TyRawPtr(mut_ty), hir::TyPtr(mut_hir_ty)) => { + search_stack.push((mut_ty.ty, &mut_hir_ty.ty)); + } + + _ => { + // FIXME there are other cases that we could trace + } + } + } + + let region_name = self.synthesize_region_name(counter); + diag.span_label( + closest_match.span, + format!("lifetime `{}` appears in this type", region_name), + ); + + return Some(region_name); + } + + /// We've found an enum/struct/union type with the substitutions + /// `substs` and -- in the HIR -- a path type with the final + /// segment `last_segment`. Try to find a `'_` to highlight in + /// the generic args (or, if not, to produce new zipped pairs of + /// types+hir to search through). + fn match_adt_and_segment<'hir>( + &self, + substs: &'tcx Substs<'tcx>, + needle_fr: RegionVid, + last_segment: &'hir hir::PathSegment, + counter: &mut usize, + diag: &mut DiagnosticBuilder<'_>, + search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty)>, + ) -> Option { + // Did the user give explicit arguments? (e.g., `Foo<..>`) + let args = last_segment.args.as_ref()?; + let lifetime = self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?; + match lifetime.name { + hir::LifetimeName::Param(_) + | hir::LifetimeName::Static + | hir::LifetimeName::Underscore => { + let region_name = self.synthesize_region_name(counter); + let ampersand_span = lifetime.span; + diag.span_label(ampersand_span, format!("let's call this `{}`", region_name)); + return Some(region_name); + } + + hir::LifetimeName::Implicit => { + // In this case, the user left off the lifetime; so + // they wrote something like: + // + // ``` + // x: Foo + // ``` + // + // where the fully elaborated form is `Foo<'_, '1, + // T>`. We don't consider this a match; instead we let + // the "fully elaborated" type fallback above handle + // it. + return None; + } + } + } + + /// We've found an enum/struct/union type with the substitutions + /// `substs` and -- in the HIR -- a path with the generic + /// arguments `args`. If `needle_fr` appears in the args, return + /// the `hir::Lifetime` that corresponds to it. If not, push onto + /// `search_stack` the types+hir to search through. + fn try_match_adt_and_generic_args<'hir>( + &self, + substs: &'tcx Substs<'tcx>, + needle_fr: RegionVid, + args: &'hir hir::GenericArgs, + search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty)>, + ) -> Option<&'hir hir::Lifetime> { + for (kind, hir_arg) in substs.iter().zip(&args.args) { + match (kind.unpack(), hir_arg) { + (UnpackedKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => { + if r.to_region_vid() == needle_fr { + return Some(lt); + } + } + + (UnpackedKind::Type(ty), hir::GenericArg::Type(hir_ty)) => { + search_stack.push((ty, hir_ty)); + } + + (UnpackedKind::Lifetime(_), _) | (UnpackedKind::Type(_), _) => { + // I *think* that HIR lowering should ensure this + // doesn't happen, even in erroneous + // programs. Else we should use delay-span-bug. + span_bug!( + hir_arg.span(), + "unmatched subst and hir arg: found {:?} vs {:?}", + kind, + hir_arg, + ); + } + } + } + + None + } + /// Find a closure upvar that contains `fr` and label it with a /// fully elaborated type, returning something like `'1`. Result /// looks like: @@ -178,7 +434,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { counter: &mut usize, diag: &mut DiagnosticBuilder<'_>, ) -> Option { - let upvar_index = self.universal_regions + let upvar_index = self + .universal_regions .defining_ty .upvar_tys(tcx) .position(|upvar_ty| { @@ -189,15 +446,16 @@ impl<'tcx> RegionInferenceContext<'tcx> { tcx.any_free_region_meets(&upvar_ty, |r| r.to_region_vid() == fr) })?; + let upvar_ty = self + .universal_regions + .defining_ty + .upvar_tys(tcx) + .nth(upvar_index); + debug!( "give_name_if_anonymous_region_appears_in_upvars: \ found {:?} in upvar {} which has type {:?}", - fr, - upvar_index, - self.universal_regions - .defining_ty - .upvar_tys(tcx) - .nth(upvar_index), + fr, upvar_index, upvar_ty, ); let region_name = self.synthesize_region_name(counter); @@ -229,9 +487,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { counter: &mut usize, diag: &mut DiagnosticBuilder<'_>, ) -> Option { - let return_ty = self.universal_regions - .unnormalized_output_ty; - debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty); + let return_ty = self.universal_regions.unnormalized_output_ty; + debug!( + "give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", + return_ty + ); if !tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) { return None; } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index ea6b39504e81d..8381adaea79de 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -689,6 +689,15 @@ impl CodeMap { self.span_until_char(sp, '{') } + /// Returns a new span representing just the start-point of this span + pub fn start_point(&self, sp: Span) -> Span { + let pos = sp.lo().0; + let width = self.find_width_of_character_at_span(sp, false); + let corrected_start_position = pos.checked_add(width).unwrap_or(pos); + let end_point = BytePos(cmp::max(corrected_start_position, sp.lo().0)); + sp.with_hi(end_point) + } + /// Returns a new span representing just the end-point of this span pub fn end_point(&self, sp: Span) -> Span { let pos = sp.hi().0; diff --git a/src/test/ui/borrowck/issue-7573.nll.stderr b/src/test/ui/borrowck/issue-7573.nll.stderr index daa0a320b88d6..5904e98753694 100644 --- a/src/test/ui/borrowck/issue-7573.nll.stderr +++ b/src/test/ui/borrowck/issue-7573.nll.stderr @@ -11,7 +11,7 @@ LL | let mut lines_to_use: Vec<&CrateId> = Vec::new(); | ---------------- lifetime `'2` appears in the type of `lines_to_use` LL | //~^ NOTE cannot infer an appropriate lifetime LL | let push_id = |installed_id: &CrateId| { - | ------------ lifetime `'1` appears in this argument + | - let's call the lifetime of this reference `'1` ... LL | lines_to_use.push(installed_id); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` diff --git a/src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr b/src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr index 5487d34813b47..c8c8ef8215ae2 100644 --- a/src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr +++ b/src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr @@ -38,7 +38,7 @@ error: unsatisfied lifetime constraints LL | let mut f: Option<&u32> = None; | ----- lifetime `'2` appears in the type of `f` LL | closure_expecting_bound(|x: &u32| { - | - lifetime `'1` appears in this argument + | - let's call the lifetime of this reference `'1` LL | f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure | ^^^^^^^^^^^ free region requires that `'1` must outlive `'2` @@ -49,7 +49,7 @@ LL | let mut f: Option<&u32> = None; | ----- lifetime `'2` appears in the type of `f` ... LL | closure_expecting_bound(|x: &'x u32| { - | - lifetime `'1` appears in this argument + | - let's call the lifetime of this reference `'1` ... LL | f = Some(x); | ^^^^^^^^^^^ free region requires that `'1` must outlive `'2` diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr index 9aad7efdee5b2..4c0b3a5d93120 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr @@ -14,7 +14,7 @@ error: unsatisfied lifetime constraints --> $DIR/static-return-lifetime-infered.rs:17:9 | LL | fn iter_values_anon(&self) -> impl Iterator { - | ----- lifetime `'1` appears in this argument + | - let's call the lifetime of this reference `'1` LL | self.x.iter().map(|a| a.0) | ^^^^^^ cast requires that `'1` must outlive `'static` diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr index 04c3ed2d6ee19..6385578698cf7 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr @@ -26,7 +26,7 @@ error: unsatisfied lifetime constraints --> $DIR/dyn-trait-underscore.rs:18:5 | LL | fn a(items: &[T]) -> Box> { - | ----- lifetime `'1` appears in this argument + | - let's call the lifetime of this reference `'1` LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime | ^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static` From aac0d914b2d776c43d6c95054815f49e19792e6e Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Mon, 9 Jul 2018 09:24:42 +0200 Subject: [PATCH 11/14] Correct some codegen stats counters --- src/librustc_codegen_llvm/builder.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 7b4998e85881e..c71e49b0d8821 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -277,7 +277,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } pub fn nswsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("nwsub"); + self.count_insn("nswsub"); unsafe { llvm::LLVMBuildNSWSub(self.llbuilder, lhs, rhs, noname()) } @@ -291,14 +291,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } pub fn fsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("sub"); + self.count_insn("fsub"); unsafe { llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname()) } } pub fn fsub_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("sub"); + self.count_insn("fsub"); unsafe { let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname()); llvm::LLVMRustSetHasUnsafeAlgebra(instr); @@ -1315,6 +1315,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } pub fn add_incoming_to_phi(&self, phi: ValueRef, val: ValueRef, bb: BasicBlockRef) { + self.count_insn("addincoming"); unsafe { llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint); } From 6b6a7a4691e5e0b3285bd7fc3ceb40ca6ce3bd84 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Mon, 9 Jul 2018 15:28:12 +0200 Subject: [PATCH 12/14] Warn windows-gnu users that the bundled gcc can't compile --- src/bootstrap/dist.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 0587dc8896d15..3343ef89d7bcf 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -308,6 +308,14 @@ fn make_win_dist( builder.copy_to_folder(&src, &target_bin_dir); } + // Warn windows-gnu users that the bundled GCC cannot compile C files + builder.create( + &target_bin_dir.join("DO NOT USE THIS gcc.exe FOR COMPILATION.txt"), + &"gcc.exe contained in this folder cannot be used for compiling C files - it is only\ + used as a linker. In order to be able to compile projects containing C code use\ + the GCC provided by MinGW or Cygwin." + ); + //Copy platform libs to platform-specific lib directory let target_lib_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("lib"); fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed"); From 7ec188b08031aa94785c068f1b3b12772425c43f Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 9 Jul 2018 15:37:02 +0100 Subject: [PATCH 13/14] Update the libc submodule --- src/liblibc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liblibc b/src/liblibc index b6d23ed45d729..37e3a22feb3d7 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit b6d23ed45d72918239c0bfac11dc547895e59b81 +Subproject commit 37e3a22feb3d75695ebfd1dd63e0e27c46e62120 From 232e77e007eb9ec847f1737cd200102e2c309cf7 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Mon, 9 Jul 2018 21:25:16 +0200 Subject: [PATCH 14/14] Change gcc warning file name, remove unnecessary reference --- src/bootstrap/dist.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 3343ef89d7bcf..e4fbabdf2318f 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -310,8 +310,8 @@ fn make_win_dist( // Warn windows-gnu users that the bundled GCC cannot compile C files builder.create( - &target_bin_dir.join("DO NOT USE THIS gcc.exe FOR COMPILATION.txt"), - &"gcc.exe contained in this folder cannot be used for compiling C files - it is only\ + &target_bin_dir.join("GCC-WARNING.txt"), + "gcc.exe contained in this folder cannot be used for compiling C files - it is only\ used as a linker. In order to be able to compile projects containing C code use\ the GCC provided by MinGW or Cygwin." );