From a7bd6c449aef07dc8daa889f4ddbdda326593e32 Mon Sep 17 00:00:00 2001 From: follower Date: Mon, 28 Sep 2020 04:05:39 +1300 Subject: [PATCH 01/29] Link to "Contributing to Rust" rather than "Getting Started". Change to link to "Contributing to Rust" chapter of `rustc` Dev Guide, primarily on the basis that the GitHub "first contribution" Issue "pop-up" says "Be sure to review the [contributing guidelines] and [code of conduct]" and links to this file. When/if the guide/"Getting Started" section gets revised to not be `rustc`-specific the linked section can be changed. In the meantime this prevents leading first time contributors into a confusing cul de sac. --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2a4c42ea0a456..b600074c19770 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,14 +2,14 @@ Thank you for your interest in contributing to Rust! -To get started, read the [Getting Started] guide in the [rustc-dev-guide]. +To get started, read the [Contributing to Rust] chapter of the [rustc-dev-guide]. ## Bug reports Did a compiler error message tell you to come here? If you want to create an ICE report, refer to [this section][contributing-bug-reports] and [open an issue][issue template]. -[Getting Started]: https://rustc-dev-guide.rust-lang.org/getting-started.html +[Contributing to Rust]: https://rustc-dev-guide.rust-lang.org/contributing.html#contributing-to-rust [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ [contributing-bug-reports]: https://rustc-dev-guide.rust-lang.org/contributing.html#bug-reports [issue template]: https://github.com/rust-lang/rust/issues/new/choose From 81edbbc2bfacd29558a5020990d49fc07ed80ac7 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 29 Sep 2020 16:35:41 +0200 Subject: [PATCH 02/29] Implement TryFrom between NonZero types. --- library/core/src/convert/num.rs | 46 +++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 336c0b26bc7d7..173d824d39083 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -485,3 +485,49 @@ nzint_impl_try_from_int! { i32, NonZeroI32, #[stable(feature = "nzint_try_from_i nzint_impl_try_from_int! { i64, NonZeroI64, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] } nzint_impl_try_from_int! { i128, NonZeroI128, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] } nzint_impl_try_from_int! { isize, NonZeroIsize, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] } + +macro_rules! nzint_impl_try_from_nzint { + ($From:ty => $To:ty, $doc: expr) => { + #[stable(feature = "nzint_try_from_nzint_conv", since = "1.48.0")] + #[doc = $doc] + impl TryFrom<$From> for $To { + type Error = TryFromIntError; + + #[inline] + fn try_from(value: $From) -> Result { + TryFrom::try_from(value.get()).map(|v| { + // SAFETY: $From is a NonZero type, so v is not zero. + unsafe { Self::new_unchecked(v) } + }) + } + } + }; + ($To:ty: $($From: ty),*) => {$( + nzint_impl_try_from_nzint!( + $From => $To, + concat!( + "Attempts to convert `", + stringify!($From), + "` to `", + stringify!($To), + "`.", + ) + ); + )*}; +} + +// Non-zero int -> non-zero unsigned int +nzint_impl_try_from_nzint! { NonZeroU8: NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } +nzint_impl_try_from_nzint! { NonZeroU16: NonZeroI8, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } +nzint_impl_try_from_nzint! { NonZeroU32: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } +nzint_impl_try_from_nzint! { NonZeroU64: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } +nzint_impl_try_from_nzint! { NonZeroU128: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroUsize, NonZeroIsize } +nzint_impl_try_from_nzint! { NonZeroUsize: NonZeroI8, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroIsize } + +// Non-zero int -> non-zero signed int +nzint_impl_try_from_nzint! { NonZeroI8: NonZeroU8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } +nzint_impl_try_from_nzint! { NonZeroI16: NonZeroU16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } +nzint_impl_try_from_nzint! { NonZeroI32: NonZeroU32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } +nzint_impl_try_from_nzint! { NonZeroI64: NonZeroU64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize } +nzint_impl_try_from_nzint! { NonZeroI128: NonZeroU128, NonZeroUsize, NonZeroIsize } +nzint_impl_try_from_nzint! { NonZeroIsize: NonZeroU16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize } From 0c32e811577fbf2ff46a607897f9ea7b6b95b364 Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Tue, 13 Oct 2020 08:30:11 +0100 Subject: [PATCH 03/29] Fixing escaping to ensure generation of welformed json. --- library/test/src/formatters/json.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/library/test/src/formatters/json.rs b/library/test/src/formatters/json.rs index 9ebc991d638cb..cfb06827be40b 100644 --- a/library/test/src/formatters/json.rs +++ b/library/test/src/formatters/json.rs @@ -39,9 +39,12 @@ impl JsonFormatter { stdout: Option>, extra: Option<&str>, ) -> io::Result<()> { + // A doc test's name includes a filename which must be escaped for correct json. self.write_message(&*format!( r#"{{ "type": "{}", "name": "{}", "event": "{}""#, - ty, name, evt + ty, + EscapedString(name), + evt ))?; if let Some(exec_time) = exec_time { self.write_message(&*format!(r#", "exec_time": "{}""#, exec_time))?; @@ -67,7 +70,7 @@ impl OutputFormatter for JsonFormatter { fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> { self.writeln_message(&*format!( r#"{{ "type": "test", "event": "started", "name": "{}" }}"#, - desc.name + EscapedString(desc.name.as_slice()) )) } @@ -140,7 +143,10 @@ impl OutputFormatter for JsonFormatter { \"name\": \"{}\", \ \"median\": {}, \ \"deviation\": {}{} }}", - desc.name, median, deviation, mbps + EscapedString(desc.name.as_slice()), + median, + deviation, + mbps ); self.writeln_message(&*line) @@ -151,7 +157,7 @@ impl OutputFormatter for JsonFormatter { fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> { self.writeln_message(&*format!( r#"{{ "type": "test", "event": "timeout", "name": "{}" }}"#, - desc.name + EscapedString(desc.name.as_slice()) )) } From a93f58f5e6c9e4e1fbc076d966a9e1e853ea06fd Mon Sep 17 00:00:00 2001 From: wcampbell Date: Tue, 13 Oct 2020 17:01:09 -0400 Subject: [PATCH 04/29] Join map operators Signed-off-by: wcampbell --- library/std/src/fs/tests.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 65a29076fefa8..38fd470a1c322 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -73,10 +73,9 @@ pub fn got_symlink_permission(tmpdir: &TempDir) -> bool { let link = tmpdir.join("some_hopefully_unique_link_name"); match symlink_file(r"nonexisting_target", link) { - Ok(_) => true, // ERROR_PRIVILEGE_NOT_HELD = 1314 Err(ref err) if err.raw_os_error() == Some(1314) => false, - Err(_) => true, + Ok(_) | Err(_) => true, } } From 964a5ac962d32c280d036df42b2e747809939cc4 Mon Sep 17 00:00:00 2001 From: wcampbell Date: Tue, 13 Oct 2020 17:01:50 -0400 Subject: [PATCH 05/29] Use is_ok() instead of empty Ok(_) Signed-off-by: wcampbell --- library/std/src/net/udp/tests.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs index 658369f79aa75..fbed3d32d451a 100644 --- a/library/std/src/net/udp/tests.rs +++ b/library/std/src/net/udp/tests.rs @@ -152,19 +152,13 @@ fn udp_clone_two_write() { let (done, rx) = channel(); let tx2 = tx.clone(); let _t = thread::spawn(move || { - match sock3.send_to(&[1], &addr2) { - Ok(..) => { - let _ = tx2.send(()); - } - Err(..) => {} + if sock3.send_to(&[1], &addr2).is_ok() { + let _ = tx2.send(()); } done.send(()).unwrap(); }); - match sock1.send_to(&[2], &addr2) { - Ok(..) => { - let _ = tx.send(()); - } - Err(..) => {} + if sock1.send_to(&[2], &addr2).is_ok() { + let _ = tx.send(()); } drop(tx); From abfbd1bd719bd1440132ead24ec64c0acd293f41 Mon Sep 17 00:00:00 2001 From: ayazhafiz Date: Tue, 13 Oct 2020 16:11:51 -0500 Subject: [PATCH 06/29] Avoid extraneous space between visibility kw and ident for statics Today, given a static like `static mut FOO: usize = 1`, rustdoc would emit `static mut FOO: usize = 1`, as it emits both the mutability kw with a space and reserves a space after the mutability kw. This patch fixes that misformatting. This patch also adds some tests for emit of other statics, as I could not find an existing test devoted to statics. --- src/librustdoc/html/render/mod.rs | 2 +- src/test/rustdoc/static.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc/static.rs diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 76334f0213d15..97d0a4d4e7dcd 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2289,7 +2289,7 @@ fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static render_attributes(w, it, false); write!( w, - "{vis}static {mutability} {name}: {typ}", + "{vis}static {mutability}{name}: {typ}", vis = it.visibility.print_with_space(), mutability = s.mutability.print_with_space(), name = it.name.as_ref().unwrap(), diff --git a/src/test/rustdoc/static.rs b/src/test/rustdoc/static.rs new file mode 100644 index 0000000000000..aa48644918d9a --- /dev/null +++ b/src/test/rustdoc/static.rs @@ -0,0 +1,12 @@ +// compile-flags: --document-private-items + +#![crate_type = "lib"] + +// @has static/static.FOO.html '//pre[@class="static"]' 'static FOO: usize' +static FOO: usize = 1; + +// @has static/static.BAR.html '//pre[@class="static"]' 'pub static BAR: usize' +pub static BAR: usize = 1; + +// @has static/static.BAZ.html '//pre[@class="static"]' 'pub static mut BAZ: usize' +pub static mut BAZ: usize = 1; From e60072f5c65c619263d137daf9afab9c6cb94c8e Mon Sep 17 00:00:00 2001 From: ayazhafiz Date: Tue, 13 Oct 2020 16:47:53 -0500 Subject: [PATCH 07/29] fixup! Avoid extraneous space between visibility kw and ident for statics --- src/test/rustdoc/static.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/rustdoc/static.rs b/src/test/rustdoc/static.rs index aa48644918d9a..90dafd8b3480d 100644 --- a/src/test/rustdoc/static.rs +++ b/src/test/rustdoc/static.rs @@ -2,11 +2,11 @@ #![crate_type = "lib"] -// @has static/static.FOO.html '//pre[@class="static"]' 'static FOO: usize' +// @has static/static.FOO.html '//pre' 'static FOO: usize' static FOO: usize = 1; -// @has static/static.BAR.html '//pre[@class="static"]' 'pub static BAR: usize' +// @has static/static.BAR.html '//pre' 'pub static BAR: usize' pub static BAR: usize = 1; -// @has static/static.BAZ.html '//pre[@class="static"]' 'pub static mut BAZ: usize' +// @has static/static.BAZ.html '//pre' 'pub static mut BAZ: usize' pub static mut BAZ: usize = 1; From 000ec5e2f8e7bf3f5da59f6f219fe02dff42d116 Mon Sep 17 00:00:00 2001 From: Ryan Scott Date: Wed, 14 Oct 2020 16:50:00 +1100 Subject: [PATCH 08/29] Made slice sort documentation consistent between stable and unstable versions --- library/alloc/src/slice.rs | 14 +++++++------- library/core/src/slice/mod.rs | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 79403cf86873e..706d563f8fba1 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -169,7 +169,7 @@ mod hack { impl [T] { /// Sorts the slice. /// - /// This sort is stable (i.e., does not reorder equal elements) and `O(n * log(n))` worst-case. + /// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*)) worst-case. /// /// When applicable, unstable sorting is preferred because it is generally faster than stable /// sorting and it doesn't allocate auxiliary memory. @@ -204,7 +204,7 @@ impl [T] { /// Sorts the slice with a comparator function. /// - /// This sort is stable (i.e., does not reorder equal elements) and `O(n * log(n))` worst-case. + /// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*)) worst-case. /// /// The comparator function must define a total ordering for the elements in the slice. If /// the ordering is not total, the order of the elements is unspecified. An order is a @@ -258,8 +258,8 @@ impl [T] { /// Sorts the slice with a key extraction function. /// - /// This sort is stable (i.e., does not reorder equal elements) and `O(m * n * log(n))` - /// worst-case, where the key function is `O(m)`. + /// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* \* log(*n*)) + /// worst-case, where the key function is *O*(*m*). /// /// For expensive key functions (e.g. functions that are not simple property accesses or /// basic operations), [`sort_by_cached_key`](#method.sort_by_cached_key) is likely to be @@ -301,8 +301,8 @@ impl [T] { /// /// During sorting, the key function is called only once per element. /// - /// This sort is stable (i.e., does not reorder equal elements) and `O(m * n + n * log(n))` - /// worst-case, where the key function is `O(m)`. + /// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* + *n* \* log(*n*)) + /// worst-case, where the key function is *O*(*m*). /// /// For simple key functions (e.g., functions that are property accesses or /// basic operations), [`sort_by_key`](#method.sort_by_key) is likely to be @@ -946,7 +946,7 @@ where /// 1. for every `i` in `1..runs.len()`: `runs[i - 1].len > runs[i].len` /// 2. for every `i` in `2..runs.len()`: `runs[i - 2].len > runs[i - 1].len + runs[i].len` /// -/// The invariants ensure that the total running time is `O(n * log(n))` worst-case. +/// The invariants ensure that the total running time is *O*(*n* \* log(*n*)) worst-case. fn merge_sort(v: &mut [T], mut is_less: F) where F: FnMut(&T, &T) -> bool, diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index d0d88c01f5b2c..3b428eba13148 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1948,10 +1948,10 @@ impl [T] { /// /// The comparator function must define a total ordering for the elements in the slice. If /// the ordering is not total, the order of the elements is unspecified. An order is a - /// total order if it is (for all a, b and c): + /// total order if it is (for all `a`, `b` and `c`): /// - /// * total and antisymmetric: exactly one of a < b, a == b or a > b is true; and - /// * transitive, a < b and b < c implies a < c. The same must hold for both == and >. + /// * total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true, and + /// * transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. /// /// For example, while [`f64`] doesn't implement [`Ord`] because `NaN != NaN`, we can use /// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`. From 8446d949f1d53b2c7ee4155f8fbf3d1390e3f203 Mon Sep 17 00:00:00 2001 From: Ryan Scott Date: Wed, 14 Oct 2020 16:58:59 +1100 Subject: [PATCH 09/29] Following #74010 by converting some newer cases of backticked O notations to be italicized --- library/alloc/src/raw_vec.rs | 2 +- library/alloc/src/vec.rs | 2 +- library/core/src/str/traits.rs | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 1844d3ae004f4..7c834f034c1f1 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -259,7 +259,7 @@ impl RawVec { /// Ensures that the buffer contains at least enough space to hold `len + /// additional` elements. If it doesn't already have enough capacity, will /// reallocate enough space plus comfortable slack space to get amortized - /// `O(1)` behavior. Will limit this behavior if it would needlessly cause + /// *O*(1) behavior. Will limit this behavior if it would needlessly cause /// itself to panic. /// /// If `len` exceeds `self.capacity()`, this may fail to actually allocate diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index 5e68f76693fcf..808adb5d47cc7 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -259,7 +259,7 @@ use crate::raw_vec::RawVec; /// `Vec` does not guarantee any particular growth strategy when reallocating /// when full, nor when [`reserve`] is called. The current strategy is basic /// and it may prove desirable to use a non-constant growth factor. Whatever -/// strategy is used will of course guarantee `O(1)` amortized [`push`]. +/// strategy is used will of course guarantee *O*(1) amortized [`push`]. /// /// `vec![x; n]`, `vec![a, b, c, d]`, and /// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec` diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 4f8aa246e5232..af1ce007e8b7c 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -89,7 +89,7 @@ fn str_index_overflow_fail() -> ! { /// self`. Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. Unlike /// other indexing operations, this can never panic. /// -/// This operation is `O(1)`. +/// This operation is *O*(1). /// /// Prior to 1.20.0, these indexing operations were still supported by /// direct implementation of `Index` and `IndexMut`. @@ -130,7 +130,7 @@ unsafe impl SliceIndex for ops::RangeFull { /// Returns a slice of the given string from the byte range /// [`begin`, `end`). /// -/// This operation is `O(1)`. +/// This operation is *O*(1). /// /// Prior to 1.20.0, these indexing operations were still supported by /// direct implementation of `Index` and `IndexMut`. @@ -237,7 +237,7 @@ unsafe impl SliceIndex for ops::Range { /// Returns a slice of the given string from the byte range [`0`, `end`). /// Equivalent to `&self[0 .. end]` or `&mut self[0 .. end]`. /// -/// This operation is `O(1)`. +/// This operation is *O*(1). /// /// Prior to 1.20.0, these indexing operations were still supported by /// direct implementation of `Index` and `IndexMut`. @@ -308,7 +308,7 @@ unsafe impl SliceIndex for ops::RangeTo { /// `len`). Equivalent to `&self[begin .. len]` or `&mut self[begin .. /// len]`. /// -/// This operation is `O(1)`. +/// This operation is *O*(1). /// /// Prior to 1.20.0, these indexing operations were still supported by /// direct implementation of `Index` and `IndexMut`. @@ -385,7 +385,7 @@ unsafe impl SliceIndex for ops::RangeFrom { /// self[begin .. end + 1]`, except if `end` has the maximum value for /// `usize`. /// -/// This operation is `O(1)`. +/// This operation is *O*(1). /// /// # Panics /// @@ -441,7 +441,7 @@ unsafe impl SliceIndex for ops::RangeInclusive { /// Equivalent to `&self [0 .. end + 1]`, except if `end` has the maximum /// value for `usize`. /// -/// This operation is `O(1)`. +/// This operation is *O*(1). /// /// # Panics /// From b9db54b3a238124b19856a03eccef7ae3ae86d91 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 15 Oct 2020 21:30:28 +0200 Subject: [PATCH 10/29] Bump nzint_try_from_nzint_conv stabilization version to 1.49. Missed the 1.48 cycle. --- library/core/src/convert/num.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 173d824d39083..2dd5e813d6fb7 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -488,7 +488,7 @@ nzint_impl_try_from_int! { isize, NonZeroIsize, #[stable(feature = "nzint_try_fr macro_rules! nzint_impl_try_from_nzint { ($From:ty => $To:ty, $doc: expr) => { - #[stable(feature = "nzint_try_from_nzint_conv", since = "1.48.0")] + #[stable(feature = "nzint_try_from_nzint_conv", since = "1.49.0")] #[doc = $doc] impl TryFrom<$From> for $To { type Error = TryFromIntError; From 5948e62f3443df626cc803fd3a08bc24e42209e8 Mon Sep 17 00:00:00 2001 From: est31 Date: Tue, 20 Oct 2020 18:38:54 +0200 Subject: [PATCH 11/29] Sync LLVM submodule if it has been initialized Since having enabled the download-ci-llvm option, and having rebased on top of f05b47ccdfa63f8b4b9fb47a9aa92381801d3ff1, I've noticed that I had to update the llvm-project submodule manually if it was checked out. Orignally, the submodule update logic was introduced to reduce the friction for contributors to manage the submodules, or in other words, to prevent getting PRs that have unwanted submodule rollbacks because the contributors didn't run git submodule update. This commit adds logic to ensure there is no inadvertent LLVM submodule rollback in a PR if download-ci-llvm (or llvm-config) is enabled. It will detect whether the llvm-project submodule is initialized, and if so, update it in any case. If it is not initialized, behaviour is kept to not do any update/initialization. An alternative to the chosen implementation would be to not pass the --init command line arg to `git submodule update` for the src/llvm-project submodule. This would show a confusing error message however on all builds with an uninitialized repo. We could pass the --silent param, but we still want it to print something if it is initialized and has to update something. So we just do a manual check for whether the submodule is initialized. --- src/bootstrap/bootstrap.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index ce37adeb28c93..a14c12a39e5e4 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -891,10 +891,15 @@ def update_submodules(self): ).decode(default_encoding).splitlines()] filtered_submodules = [] submodules_names = [] + llvm_checked_out = os.path.exists(os.path.join(self.rust_root, "src/llvm-project/.git")) for module in submodules: if module.endswith("llvm-project"): + # Don't sync the llvm-project submodule either if an external LLVM + # was provided, or if we are downloading LLVM. Also, if the + # submodule has been initialized already, sync it anyways so that + # it doesn't mess up contributor pull requests. if self.get_toml('llvm-config') or self.downloading_llvm(): - if self.get_toml('lld') != 'true': + if self.get_toml('lld') != 'true' and not llvm_checked_out: continue check = self.check_submodule(module, slow_submodules) filtered_submodules.append((module, check)) From e852a4abf01f605aa71cd529887c17c4c64f33ed Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 20 Oct 2020 16:36:46 -0700 Subject: [PATCH 12/29] Update cargo --- Cargo.lock | 15 ++++++++++++++- src/tools/cargo | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d2170a992747..034e7e34eb39e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -310,7 +310,7 @@ dependencies = [ "crypto-hash", "curl", "curl-sys", - "env_logger 0.7.1", + "env_logger 0.8.1", "filetime", "flate2", "fwdansi", @@ -1035,6 +1035,19 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54532e3223c5af90a6a757c90b5c5521564b07e5e7a958681bcd2afad421cdcd" +dependencies = [ + "atty", + "humantime 2.0.1", + "log", + "regex", + "termcolor", +] + [[package]] name = "error_index_generator" version = "0.0.0" diff --git a/src/tools/cargo b/src/tools/cargo index 79b397d72c557..dd83ae55c871d 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 79b397d72c557eb6444a2ba0dc00a211a226a35a +Subproject commit dd83ae55c871d94f060524656abab62ec40b4c40 From e0b61111f83d4465fcc439d4186710f860b05a4b Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 3 Oct 2020 14:47:28 +0100 Subject: [PATCH 13/29] Mark `repr128` as `incomplete_features` --- compiler/rustc_feature/src/active.rs | 1 + src/test/ui/enum-discriminant/discriminant_size.rs | 1 + .../ui/enum-discriminant/discriminant_size.stderr | 11 +++++++++++ .../ui/enum-discriminant/issue-70509-partial_eq.rs | 1 + .../enum-discriminant/issue-70509-partial_eq.stderr | 11 +++++++++++ src/test/ui/enum-discriminant/repr128.rs | 1 + src/test/ui/enum-discriminant/repr128.stderr | 11 +++++++++++ src/test/ui/issues/issue-43398.rs | 1 + src/test/ui/issues/issue-43398.stderr | 11 +++++++++++ 9 files changed, 49 insertions(+) create mode 100644 src/test/ui/enum-discriminant/discriminant_size.stderr create mode 100644 src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr create mode 100644 src/test/ui/enum-discriminant/repr128.stderr create mode 100644 src/test/ui/issues/issue-43398.stderr diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index c13fe2ae2806b..04912fe409679 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -622,6 +622,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::lazy_normalization_consts, sym::specialization, sym::inline_const, + sym::repr128, ]; /// Some features are not allowed to be used together at the same time, if diff --git a/src/test/ui/enum-discriminant/discriminant_size.rs b/src/test/ui/enum-discriminant/discriminant_size.rs index 4cede8c2a2ded..b939a70dfc568 100644 --- a/src/test/ui/enum-discriminant/discriminant_size.rs +++ b/src/test/ui/enum-discriminant/discriminant_size.rs @@ -1,5 +1,6 @@ // run-pass #![feature(core_intrinsics, repr128)] +//~^ WARN the feature `repr128` is incomplete use std::intrinsics::discriminant_value; diff --git a/src/test/ui/enum-discriminant/discriminant_size.stderr b/src/test/ui/enum-discriminant/discriminant_size.stderr new file mode 100644 index 0000000000000..efc7d998466cd --- /dev/null +++ b/src/test/ui/enum-discriminant/discriminant_size.stderr @@ -0,0 +1,11 @@ +warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/discriminant_size.rs:2:29 + | +LL | #![feature(core_intrinsics, repr128)] + | ^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #56071 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs index 4e2cc89948a01..ae389e1146645 100644 --- a/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs +++ b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs @@ -1,5 +1,6 @@ // run-pass #![feature(repr128, arbitrary_enum_discriminant)] +//~^ WARN the feature `repr128` is incomplete #[derive(PartialEq, Debug)] #[repr(i128)] diff --git a/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr b/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr new file mode 100644 index 0000000000000..5bf6ea56ebc77 --- /dev/null +++ b/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr @@ -0,0 +1,11 @@ +warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-70509-partial_eq.rs:2:12 + | +LL | #![feature(repr128, arbitrary_enum_discriminant)] + | ^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #56071 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/enum-discriminant/repr128.rs b/src/test/ui/enum-discriminant/repr128.rs index eefbc44f585b2..00021a07b3719 100644 --- a/src/test/ui/enum-discriminant/repr128.rs +++ b/src/test/ui/enum-discriminant/repr128.rs @@ -1,5 +1,6 @@ // run-pass #![feature(repr128, core_intrinsics, discriminant_kind)] +//~^ WARN the feature `repr128` is incomplete use std::intrinsics::discriminant_value; use std::marker::DiscriminantKind; diff --git a/src/test/ui/enum-discriminant/repr128.stderr b/src/test/ui/enum-discriminant/repr128.stderr new file mode 100644 index 0000000000000..88adfb1742d5d --- /dev/null +++ b/src/test/ui/enum-discriminant/repr128.stderr @@ -0,0 +1,11 @@ +warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/repr128.rs:2:12 + | +LL | #![feature(repr128, core_intrinsics, discriminant_kind)] + | ^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #56071 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/issues/issue-43398.rs b/src/test/ui/issues/issue-43398.rs index f0b762c6254a3..581db033f9257 100644 --- a/src/test/ui/issues/issue-43398.rs +++ b/src/test/ui/issues/issue-43398.rs @@ -2,6 +2,7 @@ #![feature(core_intrinsics)] #![feature(repr128)] +//~^ WARN the feature `repr128` is incomplete #[repr(i128)] enum Big { A, B } diff --git a/src/test/ui/issues/issue-43398.stderr b/src/test/ui/issues/issue-43398.stderr new file mode 100644 index 0000000000000..9a394153bf62f --- /dev/null +++ b/src/test/ui/issues/issue-43398.stderr @@ -0,0 +1,11 @@ +warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-43398.rs:4:12 + | +LL | #![feature(repr128)] + | ^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #56071 for more information + +warning: 1 warning emitted + From d725da129e76963ec4309edc49a34471a2b21038 Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 18 Oct 2020 21:54:10 -0700 Subject: [PATCH 14/29] Clean up and improve some docs * compiler docs * Don't format list as part of a code block * Clean up some other formatting * rustdoc book * Update CommonMark spec version to latest (0.28 -> 0.29) * Clean up some various wording and formatting --- compiler/rustc_middle/src/middle/region.rs | 22 +++++----- .../src/thir/pattern/_match.rs | 40 +++++++++++++++---- src/doc/rustdoc/src/documentation-tests.md | 28 +++++++------ 3 files changed, 58 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 38cb3c1701f92..d060549ca8137 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -292,20 +292,20 @@ pub struct ScopeTree { /// /// Then: /// - /// 1. From the ordering guarantee of HIR visitors (see - /// `rustc_hir::intravisit`), `D` does not dominate `U`. + /// 1. From the ordering guarantee of HIR visitors (see + /// `rustc_hir::intravisit`), `D` does not dominate `U`. /// - /// 2. Therefore, `D` is *potentially* storage-dead at `U` (because - /// we might visit `U` without ever getting to `D`). + /// 2. Therefore, `D` is *potentially* storage-dead at `U` (because + /// we might visit `U` without ever getting to `D`). /// - /// 3. However, we guarantee that at each HIR point, each - /// binding/temporary is always either always storage-live - /// or always storage-dead. This is what is being guaranteed - /// by `terminating_scopes` including all blocks where the - /// count of executions is not guaranteed. + /// 3. However, we guarantee that at each HIR point, each + /// binding/temporary is always either always storage-live + /// or always storage-dead. This is what is being guaranteed + /// by `terminating_scopes` including all blocks where the + /// count of executions is not guaranteed. /// - /// 4. By `2.` and `3.`, `D` is *statically* storage-dead at `U`, - /// QED. + /// 4. By `2.` and `3.`, `D` is *statically* storage-dead at `U`, + /// QED. /// /// This property ought to not on (3) in an essential way -- it /// is probably still correct even if we have "unrestricted" terminating diff --git a/compiler/rustc_mir_build/src/thir/pattern/_match.rs b/compiler/rustc_mir_build/src/thir/pattern/_match.rs index 04de9a7a58dda..7216d1305fd4b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/_match.rs @@ -78,20 +78,26 @@ //! new pattern `p`. //! //! For example, say we have the following: +//! //! ``` -//! // x: (Option, Result<()>) -//! match x { -//! (Some(true), _) => {} -//! (None, Err(())) => {} -//! (None, Err(_)) => {} -//! } +//! // x: (Option, Result<()>) +//! match x { +//! (Some(true), _) => {} +//! (None, Err(())) => {} +//! (None, Err(_)) => {} +//! } //! ``` +//! //! Here, the matrix `P` starts as: +//! +//! ``` //! [ //! [(Some(true), _)], //! [(None, Err(()))], //! [(None, Err(_))], //! ] +//! ``` +//! //! We can tell it's not exhaustive, because `U(P, _)` is true (we're not covering //! `[(Some(false), _)]`, for instance). In addition, row 3 is not useful, because //! all the values it covers are already covered by row 2. @@ -178,10 +184,14 @@ //! This special case is handled in `is_useful_specialized`. //! //! For example, if `P` is: +//! +//! ``` //! [ -//! [Some(true), _], -//! [None, 0], +//! [Some(true), _], +//! [None, 0], //! ] +//! ``` +//! //! and `p` is [Some(false), 0], then we don't care about row 2 since we know `p` only //! matches values that row 2 doesn't. For row 1 however, we need to dig into the //! arguments of `Some` to know whether some new value is covered. So we compute @@ -198,10 +208,14 @@ //! `U(P, p) := U(D(P), D(p))` //! //! For example, if `P` is: +//! +//! ``` //! [ //! [_, true, _], //! [None, false, 1], //! ] +//! ``` +//! //! and `p` is [_, false, _], the `Some` constructor doesn't appear in `P`. So if we //! only had row 2, we'd know that `p` is useful. However row 1 starts with a //! wildcard, so we need to check whether `U([[true, _]], [false, 1])`. @@ -215,10 +229,14 @@ //! `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))` //! //! For example, if `P` is: +//! +//! ``` //! [ //! [Some(true), _], //! [None, false], //! ] +//! ``` +//! //! and `p` is [_, false], both `None` and `Some` constructors appear in the first //! components of `P`. We will therefore try popping both constructors in turn: we //! compute `U([[true, _]], [_, false])` for the `Some` constructor, and `U([[false]], @@ -1496,6 +1514,7 @@ struct PatCtxt<'tcx> { /// multiple patterns. /// /// For example, if we are constructing a witness for the match against +/// /// ``` /// struct Pair(Option<(u32, u32)>, bool); /// @@ -1619,12 +1638,14 @@ fn all_constructors<'a, 'tcx>( // actually match against them all themselves. So we always return only the fictitious // constructor. // E.g., in an example like: + // // ``` // let err: io::ErrorKind = ...; // match err { // io::ErrorKind::NotFound => {}, // } // ``` + // // we don't want to show every possible IO error, but instead have only `_` as the // witness. let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty); @@ -2017,6 +2038,7 @@ crate fn is_useful<'p, 'tcx>( let mut unreachable_branches = Vec::new(); // Subpatterns that are unreachable from all branches. E.g. in the following case, the last // `true` is unreachable only from one branch, so it is overall reachable. + // // ``` // match (true, true) { // (true, true) => {} @@ -2161,10 +2183,12 @@ crate fn is_useful<'p, 'tcx>( // to do this and instead report a single `_` witness: // if the user didn't actually specify a constructor // in this arm, e.g., in + // // ``` // let x: (Direction, Direction, bool) = ...; // let (_, _, false) = x; // ``` + // // we don't want to show all 16 possible witnesses // `(, , true)` - we are // satisfied with `(_, _, true)`. In this case, diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md index 18010bebcf0e7..387d86189b08f 100644 --- a/src/doc/rustdoc/src/documentation-tests.md +++ b/src/doc/rustdoc/src/documentation-tests.md @@ -16,8 +16,8 @@ The basic idea is this: The triple backticks start and end code blocks. If this were in a file named `foo.rs`, running `rustdoc --test foo.rs` will extract this example, and then run it as a test. -Please note that by default, if no language is set for the block code, `rustdoc` -assumes it is `Rust` code. So the following: +Please note that by default, if no language is set for the block code, rustdoc +assumes it is Rust code. So the following: ``````markdown ```rust @@ -44,7 +44,6 @@ the `assert!` family of macros works the same as other Rust code: ```rust let foo = "foo"; - assert_eq!(foo, "foo"); ``` @@ -55,8 +54,9 @@ the code panics and the doctest fails. In the example above, you'll note something strange: there's no `main` function! Forcing you to write `main` for every example, no matter how small, -adds friction. So `rustdoc` processes your examples slightly before -running them. Here's the full algorithm rustdoc uses to preprocess examples: +adds friction and clutters the output. So `rustdoc` processes your examples +slightly before running them. Here's the full algorithm `rustdoc` uses to +preprocess examples: 1. Some common `allow` attributes are inserted, including `unused_variables`, `unused_assignments`, `unused_mut`, @@ -78,10 +78,12 @@ Sometimes, you need some setup code, or other things that would distract from your example, but are important to make the tests work. Consider an example block that looks like this: -```text +```ignore +/// ``` /// /// Some documentation. /// # fn foo() {} // this function will be hidden /// println!("Hello, World!"); +/// ``` ``` It will render like this: @@ -251,7 +253,7 @@ disambiguate the error type: This is an unfortunate consequence of the `?` operator adding an implicit conversion, so type inference fails because the type is not unique. Please note that you must write the `(())` in one sequence without intermediate whitespace -so that rustdoc understands you want an implicit `Result`-returning function. +so that `rustdoc` understands you want an implicit `Result`-returning function. ## Documenting macros @@ -359,7 +361,7 @@ the code with the 2015 edition. ## Syntax reference The *exact* syntax for code blocks, including the edge cases, can be found -in the [Fenced Code Blocks](https://spec.commonmark.org/0.28/#fenced-code-blocks) +in the [Fenced Code Blocks](https://spec.commonmark.org/0.29/#fenced-code-blocks) section of the CommonMark specification. Rustdoc also accepts *indented* code blocks as an alternative to fenced @@ -372,7 +374,7 @@ can indent each line by four or more spaces. `````` These, too, are documented in the CommonMark specification, in the -[Indented Code Blocks](https://spec.commonmark.org/0.28/#indented-code-blocks) +[Indented Code Blocks](https://spec.commonmark.org/0.29/#indented-code-blocks) section. However, it's preferable to use fenced code blocks over indented code blocks. @@ -388,7 +390,7 @@ documentation. To this end, Rustdoc allows you to have certain items only appear collecting doctests, so you can utilize doctest functionality without forcing the test to appear in docs, or to find an arbitrary private item to include it on. -When compiling a crate for use in doctests (with `--test` option), rustdoc will set `cfg(doctest)`. +When compiling a crate for use in doctests (with `--test` option), `rustdoc` will set `#[cfg(doctest)]`. Note that they will still link against only the public items of your crate; if you need to test private items, you need to write a unit test. @@ -407,18 +409,18 @@ pub struct MyStructOnlyTakesUsize; ``` Note that the struct `MyStructOnlyTakesUsize` here isn't actually part of your public crate -API. The use of `#[cfg(doctest)]` makes sure that this struct only exists while rustdoc is +API. The use of `#[cfg(doctest)]` makes sure that this struct only exists while `rustdoc` is collecting doctests. This means that its doctest is executed when `--test` is passed to rustdoc, but is hidden from the public documentation. -Another possible use of `cfg(doctest)` is to test doctests that are included in your README file +Another possible use of `#[cfg(doctest)]` is to test doctests that are included in your README file without including it in your main documentation. For example, you could write this into your `lib.rs` to test your README as part of your doctests: ```rust,ignore #![feature(external_doc)] -#[doc(include="../README.md")] +#[doc(include = "../README.md")] #[cfg(doctest)] pub struct ReadmeDoctests; ``` From 769b4108e288c4074b502336a38a5c39bfff555a Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Thu, 22 Oct 2020 13:55:19 +0200 Subject: [PATCH 15/29] Make closures inherit the parent function's target features --- compiler/rustc_typeck/src/collect.rs | 10 +++++++++- .../closures-inherit-target_feature.rs | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index ac2a4a464a782..b30fb7be273f1 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -40,7 +40,7 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::Discr; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt}; use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness}; use rustc_session::config::SanitizerSet; use rustc_session::lint; @@ -2786,6 +2786,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } }); + // #73631: closures inherit `#[target_feature]` annotations + if tcx.features().target_feature_11 && tcx.is_closure(id) { + let owner_id = tcx.parent(id).expect("closure should have a parent"); + codegen_fn_attrs + .target_features + .extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied()) + } + // If a function uses #[target_feature] it can't be inlined into general // purpose functions as they wouldn't have the right target features // enabled. For that reason we also forbid #[inline(always)] as it can't be diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs b/src/test/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs new file mode 100644 index 0000000000000..e6c81f56ab863 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs @@ -0,0 +1,18 @@ +// Tests #73631: closures inherit `#[target_feature]` annotations + +// check-pass +// only-x86_64 + +#![feature(target_feature_11)] + +#[target_feature(enable="avx")] +fn also_use_avx() { + println!("Hello from AVX") +} + +#[target_feature(enable="avx")] +fn use_avx() -> Box { + Box::new(|| also_use_avx()) +} + +fn main() {} \ No newline at end of file From 683db310c4a2e205bd954ea030cff3ce2fa9ef68 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 22 Oct 2020 13:23:14 +0100 Subject: [PATCH 16/29] Fix clippy tests --- src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs | 1 + src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs | 1 + src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs | 1 + 3 files changed, 3 insertions(+) diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs index de670cdfc31f1..e370a98df1acf 100644 --- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs @@ -3,6 +3,7 @@ #![crate_type = "proc-macro"] #![feature(repr128, proc_macro_hygiene, proc_macro_quote, box_patterns)] +#![allow(incomplete_features)] #![allow(clippy::useless_conversion)] extern crate proc_macro; diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs index 3df8be6c23230..cd5a5ae0aa75a 100644 --- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs @@ -3,6 +3,7 @@ #![crate_type = "proc-macro"] #![feature(repr128, proc_macro_quote)] +#![allow(incomplete_features)] extern crate proc_macro; diff --git a/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs b/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs index 619d11cefc46d..ed8e7a708a5e2 100644 --- a/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs +++ b/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs @@ -6,6 +6,7 @@ // contain a proc-macro. #![feature(repr128)] +#![allow(incomplete_features)] #![crate_type = "proc-macro"] extern crate proc_macro; From b4a9854afe0ab75f1b0e0c46a9342c835d5bf7b9 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Thu, 22 Oct 2020 14:37:42 +0200 Subject: [PATCH 17/29] Fixup: add missing trailing newline --- .../closures-inherit-target_feature.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs b/src/test/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs index e6c81f56ab863..af35bc2014bfe 100644 --- a/src/test/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs @@ -15,4 +15,4 @@ fn use_avx() -> Box { Box::new(|| also_use_avx()) } -fn main() {} \ No newline at end of file +fn main() {} From 36a5244da311b9cd9a4ee04a75f15e23cf9fe891 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 22 Oct 2020 09:47:23 -0400 Subject: [PATCH 18/29] Explain where the closure return type was inferred Fixes #78193 --- compiler/rustc_typeck/src/check/coercion.rs | 22 +++++++++++++++++++ .../closures/closure-return-type-mismatch.rs | 17 ++++++++++++++ .../closure-return-type-mismatch.stderr | 21 ++++++++++++++++++ .../type-mismatch-signature-deduction.stderr | 5 +++++ 4 files changed, 65 insertions(+) create mode 100644 src/test/ui/closures/closure-return-type-mismatch.rs create mode 100644 src/test/ui/closures/closure-return-type-mismatch.stderr diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index c1485e3baf677..6da3ecde329cf 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1475,6 +1475,28 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.borrow().as_ref(), fn_output) { self.add_impl_trait_explanation(&mut err, cause, fcx, expected, *sp, fn_output); } + + if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() { + // If the closure has an explicit return type annotation, + // then a type error may occur at the first return expression we + // see in the closure (if it conflicts with the declared + // return type). Skip adding a note in this case, since it + // would be incorrect. + if !err.span.primary_spans().iter().any(|span| span == sp) { + let hir = fcx.tcx.hir(); + let body_owner = hir.body_owned_by(hir.enclosing_body_owner(fcx.body_id)); + if fcx.tcx.is_closure(hir.body_owner_def_id(body_owner).to_def_id()) { + err.span_note( + *sp, + &format!( + "return type inferred to be `{}` here", + fcx.resolve_vars_if_possible(&expected) + ), + ); + } + } + } + err } diff --git a/src/test/ui/closures/closure-return-type-mismatch.rs b/src/test/ui/closures/closure-return-type-mismatch.rs new file mode 100644 index 0000000000000..1631bb303e54e --- /dev/null +++ b/src/test/ui/closures/closure-return-type-mismatch.rs @@ -0,0 +1,17 @@ +fn main() { + || { + if false { + return "test"; + } + let a = true; + a //~ ERROR mismatched types + }; + + || -> bool { + if false { + return "hello" //~ ERROR mismatched types + }; + let b = true; + b + }; +} diff --git a/src/test/ui/closures/closure-return-type-mismatch.stderr b/src/test/ui/closures/closure-return-type-mismatch.stderr new file mode 100644 index 0000000000000..3a89d30a05d20 --- /dev/null +++ b/src/test/ui/closures/closure-return-type-mismatch.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/closure-return-type-mismatch.rs:7:9 + | +LL | a + | ^ expected `&str`, found `bool` + | +note: return type inferred to be `&str` here + --> $DIR/closure-return-type-mismatch.rs:4:20 + | +LL | return "test"; + | ^^^^^^ + +error[E0308]: mismatched types + --> $DIR/closure-return-type-mismatch.rs:12:20 + | +LL | return "hello" + | ^^^^^^^ expected `bool`, found `&str` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr index 9e111d68a55b7..4abc0542c5142 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -6,6 +6,11 @@ LL | 5 | = note: expected type `std::result::Result<{integer}, _>` found type `{integer}` +note: return type inferred to be `std::result::Result<{integer}, _>` here + --> $DIR/type-mismatch-signature-deduction.rs:8:20 + | +LL | return Ok(6); + | ^^^^^ error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:6:5: 14:6] as Generator>::Return == i32` --> $DIR/type-mismatch-signature-deduction.rs:5:13 From 954b5a81b46f60df640f36cfc83f04cd2a965051 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 20 Oct 2020 19:14:17 -0300 Subject: [PATCH 19/29] Rename parse_const_expr to parse_const_block --- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 2 +- compiler/rustc_parse/src/parser/pat.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 698a7e7d9cde8..51ecc53ca261f 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1063,7 +1063,7 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Unsafe) { self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs) } else if self.check_inline_const() { - self.parse_const_expr(lo.to(self.token.span)) + self.parse_const_block(lo.to(self.token.span)) } else if self.is_do_catch_block() { self.recover_do_catch(attrs) } else if self.is_try_block() { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index fb825256d92cd..4999498e4f73c 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -864,7 +864,7 @@ impl<'a> Parser<'a> { } /// Parses inline const expressions. - fn parse_const_expr(&mut self, span: Span) -> PResult<'a, P> { + fn parse_const_block(&mut self, span: Span) -> PResult<'a, P> { self.sess.gated_spans.gate(sym::inline_const, span); self.eat_keyword(kw::Const); let blk = self.parse_block()?; diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 15db2066a3053..356743f20713a 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -315,7 +315,7 @@ impl<'a> Parser<'a> { PatKind::Box(pat) } else if self.check_inline_const() { // Parse `const pat` - PatKind::Lit(self.parse_const_expr(lo.to(self.token.span))?) + PatKind::Lit(self.parse_const_block(lo.to(self.token.span))?) } else if self.can_be_ident_pat() { // Parse `ident @ pat` // This can give false positives and parse nullary enums, From f8842b9bacaf277430fa5c6cdf430b046dc7f323 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 19 Oct 2020 16:18:47 -0300 Subject: [PATCH 20/29] Make inline const work in range patterns --- compiler/rustc_parse/src/parser/pat.rs | 21 ++++++++++++----- .../ui/inline-const/const-match-pat-range.rs | 23 +++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/inline-const/const-match-pat-range.rs diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 356743f20713a..8da0a2f57d876 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -315,7 +315,13 @@ impl<'a> Parser<'a> { PatKind::Box(pat) } else if self.check_inline_const() { // Parse `const pat` - PatKind::Lit(self.parse_const_block(lo.to(self.token.span))?) + let const_expr = self.parse_const_block(lo.to(self.token.span))?; + + if let Some(re) = self.parse_range_end() { + self.parse_pat_range_begin_with(const_expr, re)? + } else { + PatKind::Lit(const_expr) + } } else if self.can_be_ident_pat() { // Parse `ident @ pat` // This can give false positives and parse nullary enums, @@ -716,17 +722,20 @@ impl<'a> Parser<'a> { } /// Is the token `dist` away from the current suitable as the start of a range patterns end? - fn is_pat_range_end_start(&self, dist: usize) -> bool { - self.look_ahead(dist, |t| { - t.is_path_start() // e.g. `MY_CONST`; + fn is_pat_range_end_start(&mut self, dist: usize) -> bool { + self.check_inline_const() + || self.look_ahead(dist, |t| { + t.is_path_start() // e.g. `MY_CONST`; || t.kind == token::Dot // e.g. `.5` for recovery; || t.can_begin_literal_maybe_minus() // e.g. `42`. || t.is_whole_expr() - }) + }) } fn parse_pat_range_end(&mut self) -> PResult<'a, P> { - if self.check_path() { + if self.check_inline_const() { + self.parse_const_block(self.token.span) + } else if self.check_path() { let lo = self.token.span; let (qself, path) = if self.eat_lt() { // Parse a qualified path diff --git a/src/test/ui/inline-const/const-match-pat-range.rs b/src/test/ui/inline-const/const-match-pat-range.rs new file mode 100644 index 0000000000000..4fbccfaf20064 --- /dev/null +++ b/src/test/ui/inline-const/const-match-pat-range.rs @@ -0,0 +1,23 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(inline_const)] +fn main() { + const N: u32 = 10; + let x: u32 = 3; + + match x { + const { N - 1 } ..= 10 => {}, + _ => {}, + } + + match x { + const { N - 1 } ..= const { N + 1 } => {}, + _ => {}, + } + + match x { + 1 ..= const { N + 1 } => {}, + _ => {}, + } +} From 83abed9df6ad0a8881270f166a02ffcaf437422f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 19 Oct 2020 18:44:37 -0300 Subject: [PATCH 21/29] Make inline const work for half open ranges --- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 6 +++--- compiler/rustc_parse/src/parser/pat.rs | 8 ++++---- src/test/ui/inline-const/const-match-pat-range.rs | 12 +++++++++++- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 51ecc53ca261f..78c95428c7211 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1062,7 +1062,7 @@ impl<'a> Parser<'a> { }) } else if self.eat_keyword(kw::Unsafe) { self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs) - } else if self.check_inline_const() { + } else if self.check_inline_const(0) { self.parse_const_block(lo.to(self.token.span)) } else if self.is_do_catch_block() { self.recover_do_catch(attrs) diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 4999498e4f73c..8ff97453c1414 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -522,9 +522,9 @@ impl<'a> Parser<'a> { self.check_or_expected(self.token.can_begin_const_arg(), TokenType::Const) } - fn check_inline_const(&mut self) -> bool { - self.check_keyword(kw::Const) - && self.look_ahead(1, |t| match t.kind { + fn check_inline_const(&self, dist: usize) -> bool { + self.is_keyword_ahead(dist, &[kw::Const]) + && self.look_ahead(dist + 1, |t| match t.kind { token::Interpolated(ref nt) => matches!(**nt, token::NtBlock(..)), token::OpenDelim(DelimToken::Brace) => true, _ => false, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 8da0a2f57d876..27fe75a23b6a8 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -313,7 +313,7 @@ impl<'a> Parser<'a> { let pat = self.parse_pat_with_range_pat(false, None)?; self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_token.span)); PatKind::Box(pat) - } else if self.check_inline_const() { + } else if self.check_inline_const(0) { // Parse `const pat` let const_expr = self.parse_const_block(lo.to(self.token.span))?; @@ -722,8 +722,8 @@ impl<'a> Parser<'a> { } /// Is the token `dist` away from the current suitable as the start of a range patterns end? - fn is_pat_range_end_start(&mut self, dist: usize) -> bool { - self.check_inline_const() + fn is_pat_range_end_start(&self, dist: usize) -> bool { + self.check_inline_const(dist) || self.look_ahead(dist, |t| { t.is_path_start() // e.g. `MY_CONST`; || t.kind == token::Dot // e.g. `.5` for recovery; @@ -733,7 +733,7 @@ impl<'a> Parser<'a> { } fn parse_pat_range_end(&mut self) -> PResult<'a, P> { - if self.check_inline_const() { + if self.check_inline_const(0) { self.parse_const_block(self.token.span) } else if self.check_path() { let lo = self.token.span; diff --git a/src/test/ui/inline-const/const-match-pat-range.rs b/src/test/ui/inline-const/const-match-pat-range.rs index 4fbccfaf20064..c50c4f42848ec 100644 --- a/src/test/ui/inline-const/const-match-pat-range.rs +++ b/src/test/ui/inline-const/const-match-pat-range.rs @@ -1,7 +1,7 @@ // build-pass #![allow(incomplete_features)] -#![feature(inline_const)] +#![feature(inline_const, half_open_range_patterns, exclusive_range_pattern)] fn main() { const N: u32 = 10; let x: u32 = 3; @@ -20,4 +20,14 @@ fn main() { 1 ..= const { N + 1 } => {}, _ => {}, } + + match x { + .. const { N + 1 } => {}, + _ => {}, + } + + match x { + const { N - 1 } .. => {}, + _ => {}, + } } From 5bef429dacb216b45a6bfa4c020d108c1d8e726e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 20 Oct 2020 18:53:13 -0300 Subject: [PATCH 22/29] Add ..= const { .. } missing tests and sort them properly --- src/test/ui/inline-const/const-match-pat-range.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/test/ui/inline-const/const-match-pat-range.rs b/src/test/ui/inline-const/const-match-pat-range.rs index c50c4f42848ec..eefe43a1a2297 100644 --- a/src/test/ui/inline-const/const-match-pat-range.rs +++ b/src/test/ui/inline-const/const-match-pat-range.rs @@ -7,17 +7,17 @@ fn main() { let x: u32 = 3; match x { - const { N - 1 } ..= 10 => {}, + 1 ..= const { N + 1 } => {}, _ => {}, } match x { - const { N - 1 } ..= const { N + 1 } => {}, + const { N - 1 } ..= 10 => {}, _ => {}, } match x { - 1 ..= const { N + 1 } => {}, + const { N - 1 } ..= const { N + 1 } => {}, _ => {}, } @@ -30,4 +30,9 @@ fn main() { const { N - 1 } .. => {}, _ => {}, } + + match x { + ..= const { N + 1 } => {}, + _ => {} + } } From 5656a4151e07651df154911672055260f51614fd Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 20 Oct 2020 19:59:22 -0300 Subject: [PATCH 23/29] Bless tests --- src/test/ui/parser/issue-66357-unexpected-unreachable.rs | 2 +- src/test/ui/parser/issue-66357-unexpected-unreachable.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs index 7b95bc775ba91..5ec143fae2344 100644 --- a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs +++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs @@ -13,4 +13,4 @@ fn f() { |[](* } //~^ ERROR expected one of `,` or `:`, found `(` -//~| ERROR expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `const`, `mut`, `ref`, `|`, identifier, or path, found `*` +//~| ERROR expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr index 5549f73920d4f..c3810999d2395 100644 --- a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr +++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr @@ -4,7 +4,7 @@ error: expected one of `,` or `:`, found `(` LL | fn f() { |[](* } | ^ expected one of `,` or `:` -error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `const`, `mut`, `ref`, `|`, identifier, or path, found `*` +error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` --> $DIR/issue-66357-unexpected-unreachable.rs:14:14 | LL | fn f() { |[](* } From 13bc087a73e6a5bf500b7f52cf391ca4df98841f Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 18 Oct 2020 18:17:49 -0700 Subject: [PATCH 24/29] Clean up lib docs --- library/alloc/src/string.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 1bec9e0ff26be..72ed036637d8b 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1,8 +1,8 @@ -//! A UTF-8 encoded, growable string. +//! A UTF-8–encoded, growable string. //! -//! This module contains the [`String`] type, a trait for converting -//! [`ToString`]s, and several error types that may result from working with -//! [`String`]s. +//! This module contains the [`String`] type, the [`ToString`] trait for +//! converting to strings, and several error types that may result from +//! working with [`String`]s. //! //! # Examples //! @@ -57,7 +57,7 @@ use crate::collections::TryReserveError; use crate::str::{self, from_boxed_utf8_unchecked, Chars, FromStr, Utf8Error}; use crate::vec::Vec; -/// A UTF-8 encoded, growable string. +/// A UTF-8–encoded, growable string. /// /// The `String` type is the most common string type that has ownership over the /// contents of the string. It has a close relationship with its borrowed @@ -565,7 +565,7 @@ impl String { Cow::Owned(res) } - /// Decode a UTF-16 encoded vector `v` into a `String`, returning [`Err`] + /// Decode a UTF-16–encoded vector `v` into a `String`, returning [`Err`] /// if `v` contains any invalid data. /// /// # Examples @@ -599,7 +599,7 @@ impl String { Ok(ret) } - /// Decode a UTF-16 encoded slice `v` into a `String`, replacing + /// Decode a UTF-16–encoded slice `v` into a `String`, replacing /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. /// /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], @@ -2191,8 +2191,9 @@ pub trait ToString { #[stable(feature = "rust1", since = "1.0.0")] impl ToString for T { // A common guideline is to not inline generic functions. However, - // remove `#[inline]` from this method causes non-negligible regression. - // See as last attempt try to remove it. + // removing `#[inline]` from this method causes non-negligible regressions. + // See , the last attempt + // to try to remove it. #[inline] default fn to_string(&self) -> String { use fmt::Write; From f82adf5bdba6e2a9fe4a42c9d260f20b60b33960 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 22 Oct 2020 16:08:26 -0700 Subject: [PATCH 25/29] Add test of incompatible match arm types with multiline arm --- src/test/ui/match/match-incompat-type-semi.rs | 10 ++++++++++ .../ui/match/match-incompat-type-semi.stderr | 20 ++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/test/ui/match/match-incompat-type-semi.rs b/src/test/ui/match/match-incompat-type-semi.rs index 9ab40fa3cce94..37f6beabd3302 100644 --- a/src/test/ui/match/match-incompat-type-semi.rs +++ b/src/test/ui/match/match-incompat-type-semi.rs @@ -39,4 +39,14 @@ fn main() { None => { //~ ERROR incompatible types }, }; + + let _ = match Some(42) { + Some(x) => "rust-lang.org" + .chars() + .skip(1) + .chain(Some(x as u8 as char)) + .take(10) + .any(char::is_alphanumeric), + None => {} //~ ERROR incompatible types + }; } diff --git a/src/test/ui/match/match-incompat-type-semi.stderr b/src/test/ui/match/match-incompat-type-semi.stderr index 701f15fdc4b60..1a2dbbcc29fb3 100644 --- a/src/test/ui/match/match-incompat-type-semi.stderr +++ b/src/test/ui/match/match-incompat-type-semi.stderr @@ -69,6 +69,24 @@ LL | || }, LL | | }; | |_____- `match` arms have incompatible types -error: aborting due to 4 previous errors +error[E0308]: `match` arms have incompatible types + --> $DIR/match-incompat-type-semi.rs:50:17 + | +LL | let _ = match Some(42) { + | _____________- +LL | | Some(x) => "rust-lang.org" + | |____________________- +LL | || .chars() +LL | || .skip(1) +LL | || .chain(Some(x as u8 as char)) +LL | || .take(10) +LL | || .any(char::is_alphanumeric), + | ||_______________________________________- this is found to be of type `bool` +LL | | None => {} + | | ^^ expected `bool`, found `()` +LL | | }; + | |_____- `match` arms have incompatible types + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0308`. From b0059500f6765612fbda6d33240116f7520d433a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 22 Oct 2020 14:20:02 -0700 Subject: [PATCH 26/29] Reduce diagram mess in 'match arms have incompatible types' error --- .../src/infer/error_reporting/mod.rs | 16 ++++++- compiler/rustc_middle/src/traits/mod.rs | 1 + compiler/rustc_typeck/src/check/_match.rs | 1 + .../ui/match/match-incompat-type-semi.stderr | 48 +++++++++---------- 4 files changed, 38 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 795c5a64d26b7..3a0ec6327c186 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -619,6 +619,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { scrut_hir_id, opt_suggest_box_span, arm_span, + scrut_span, .. }) => match source { hir::MatchSource::IfLetDesugar { .. } => { @@ -664,18 +665,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { Some(ty::error::ExpectedFound { expected, .. }) => expected, _ => last_ty, }); - let msg = "`match` arms have incompatible types"; - err.span_label(cause.span, msg); + let source_map = self.tcx.sess.source_map(); + let mut any_multiline_arm = source_map.is_multiline(arm_span); if prior_arms.len() <= 4 { for sp in prior_arms { + any_multiline_arm |= source_map.is_multiline(*sp); err.span_label(*sp, format!("this is found to be of type `{}`", t)); } } else if let Some(sp) = prior_arms.last() { + any_multiline_arm |= source_map.is_multiline(*sp); err.span_label( *sp, format!("this and all prior arms are found to be of type `{}`", t), ); } + let outer_error_span = if any_multiline_arm { + // Cover just `match` and the scrutinee expression, not + // the entire match body, to reduce diagram noise. + cause.span.shrink_to_lo().to(scrut_span) + } else { + cause.span + }; + let msg = "`match` arms have incompatible types"; + err.span_label(outer_error_span, msg); if let Some(sp) = semi_span { err.span_suggestion_short( sp, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 26962aa108342..bbc46b8d60835 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -343,6 +343,7 @@ static_assert_size!(ObligationCauseCode<'_>, 32); #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] pub struct MatchExpressionArmCause<'tcx> { pub arm_span: Span, + pub scrut_span: Span, pub semi_span: Option, pub source: hir::MatchSource, pub prior_arms: Vec, diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index 7cb23dc053795..398e013e62fb5 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -201,6 +201,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr.span, ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { arm_span, + scrut_span: scrut.span, semi_span, source: match_src, prior_arms: other_arms.clone(), diff --git a/src/test/ui/match/match-incompat-type-semi.stderr b/src/test/ui/match/match-incompat-type-semi.stderr index 1a2dbbcc29fb3..008b1c1e93d6d 100644 --- a/src/test/ui/match/match-incompat-type-semi.stderr +++ b/src/test/ui/match/match-incompat-type-semi.stderr @@ -56,36 +56,32 @@ LL | | }; error[E0308]: `match` arms have incompatible types --> $DIR/match-incompat-type-semi.rs:39:17 | -LL | let _ = match Some(42) { - | _____________- -LL | | Some(x) => { -LL | | x - | | - this is found to be of type `{integer}` -LL | | }, -LL | | None => { - | |_________________^ -LL | || }, - | ||_________^ expected integer, found `()` -LL | | }; - | |_____- `match` arms have incompatible types +LL | let _ = match Some(42) { + | -------------- `match` arms have incompatible types +LL | Some(x) => { +LL | x + | - this is found to be of type `{integer}` +LL | }, +LL | None => { + | _________________^ +LL | | }, + | |_________^ expected integer, found `()` error[E0308]: `match` arms have incompatible types --> $DIR/match-incompat-type-semi.rs:50:17 | -LL | let _ = match Some(42) { - | _____________- -LL | | Some(x) => "rust-lang.org" - | |____________________- -LL | || .chars() -LL | || .skip(1) -LL | || .chain(Some(x as u8 as char)) -LL | || .take(10) -LL | || .any(char::is_alphanumeric), - | ||_______________________________________- this is found to be of type `bool` -LL | | None => {} - | | ^^ expected `bool`, found `()` -LL | | }; - | |_____- `match` arms have incompatible types +LL | let _ = match Some(42) { + | -------------- `match` arms have incompatible types +LL | Some(x) => "rust-lang.org" + | ____________________- +LL | | .chars() +LL | | .skip(1) +LL | | .chain(Some(x as u8 as char)) +LL | | .take(10) +LL | | .any(char::is_alphanumeric), + | |_______________________________________- this is found to be of type `bool` +LL | None => {} + | ^^ expected `bool`, found `()` error: aborting due to 5 previous errors From 5b32c84952a5d734839a486d77f07dfe995bcae7 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 23 Oct 2020 16:10:19 +0900 Subject: [PATCH 27/29] Add a regression test for issue-72616 --- src/test/ui/inference/issue-72616.rs | 29 ++++++++++++++++++++++++ src/test/ui/inference/issue-72616.stderr | 13 +++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/test/ui/inference/issue-72616.rs create mode 100644 src/test/ui/inference/issue-72616.stderr diff --git a/src/test/ui/inference/issue-72616.rs b/src/test/ui/inference/issue-72616.rs new file mode 100644 index 0000000000000..5e5a3babfe020 --- /dev/null +++ b/src/test/ui/inference/issue-72616.rs @@ -0,0 +1,29 @@ +// Regression test for #72616, it used to emit incorrect diagnostics, like: +// error[E0283]: type annotations needed for `String` +// --> src/main.rs:8:30 +// | +// 5 | let _: String = "".to_owned().try_into().unwrap(); +// | - consider giving this pattern a type +// ... +// 8 | if String::from("a") == "a".try_into().unwrap() {} +// | ^^ cannot infer type for struct `String` +// | +// = note: cannot satisfy `String: PartialEq<_>` + +use std::convert::TryInto; + +pub fn main() { + { + let _: String = "".to_owned().try_into().unwrap(); + } + { + if String::from("a") == "a".try_into().unwrap() {} + //~^ ERROR: type annotations needed + } + { + let _: String = match "_".try_into() { + Ok(a) => a, + Err(_) => "".into(), + }; + } +} diff --git a/src/test/ui/inference/issue-72616.stderr b/src/test/ui/inference/issue-72616.stderr new file mode 100644 index 0000000000000..d811988c9c1d0 --- /dev/null +++ b/src/test/ui/inference/issue-72616.stderr @@ -0,0 +1,13 @@ +error[E0283]: type annotations needed + --> $DIR/issue-72616.rs:20:30 + | +LL | if String::from("a") == "a".try_into().unwrap() {} + | ^^ -------------- this method call resolves to `std::result::Result>::Error>` + | | + | cannot infer type + | + = note: cannot satisfy `String: PartialEq<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. From 043fab3fd5731d9b3e76468c1d92445c4f11bebb Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 23 Oct 2020 16:11:46 +0900 Subject: [PATCH 28/29] Make it regression test of issue-77668 --- .../ui/issues/issue-50865-private-impl-trait/auxiliary/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/ui/issues/issue-50865-private-impl-trait/auxiliary/lib.rs b/src/test/ui/issues/issue-50865-private-impl-trait/auxiliary/lib.rs index f3a51b415faca..fb4bf2b8b44e7 100644 --- a/src/test/ui/issues/issue-50865-private-impl-trait/auxiliary/lib.rs +++ b/src/test/ui/issues/issue-50865-private-impl-trait/auxiliary/lib.rs @@ -1,3 +1,7 @@ +// revisions: default miropt +//[miropt]compile-flags: -Z mir-opt-level=2 +// ~^ This flag is for #77668, it used to be ICE. + #![crate_type = "lib"] pub fn bar

( // Error won't happen if "bar" is not generic From 98e13169ad9ca564def675ca61f7c072d399cb0d Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 23 Oct 2020 16:22:11 +0900 Subject: [PATCH 29/29] Add regression test for issue-71732 --- src/test/ui/inference/issue-71732.rs | 23 +++++++++++++++++++++++ src/test/ui/inference/issue-71732.stderr | 13 +++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/test/ui/inference/issue-71732.rs create mode 100644 src/test/ui/inference/issue-71732.stderr diff --git a/src/test/ui/inference/issue-71732.rs b/src/test/ui/inference/issue-71732.rs new file mode 100644 index 0000000000000..30063a0957c74 --- /dev/null +++ b/src/test/ui/inference/issue-71732.rs @@ -0,0 +1,23 @@ +// Regression test for #71732, it used to emit incorrect diagnostics, like: +// error[E0283]: type annotations needed +// --> src/main.rs:5:10 +// | +// 5 | .get(&"key".into()) +// | ^^^ cannot infer type for struct `String` +// | +// = note: cannot satisfy `String: Borrow<_>` +// help: consider specifying the type argument in the method call +// | +// 5 | .get::(&"key".into()) +// | + +use std::collections::hash_map::HashMap; + +fn foo(parameters: &HashMap) -> bool { + parameters + .get(&"key".into()) //~ ERROR: type annotations needed + .and_then(|found: &String| Some(false)) + .unwrap_or(false) +} + +fn main() {} diff --git a/src/test/ui/inference/issue-71732.stderr b/src/test/ui/inference/issue-71732.stderr new file mode 100644 index 0000000000000..17fad571385dc --- /dev/null +++ b/src/test/ui/inference/issue-71732.stderr @@ -0,0 +1,13 @@ +error[E0283]: type annotations needed + --> $DIR/issue-71732.rs:18:10 + | +LL | .get(&"key".into()) + | ^^^ ------------ this method call resolves to `T` + | | + | cannot infer type for type parameter `Q` declared on the associated function `get` + | + = note: cannot satisfy `String: Borrow<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`.