From 3ed618443437307749e4c773f260c2b4b94673f5 Mon Sep 17 00:00:00 2001 From: Ryan Lopopolo Date: Sun, 14 Feb 2021 15:01:46 -0800 Subject: [PATCH 01/14] Implement Extend and FromIterator for OsString Add the following trait impls: - `impl Extend for OsString` - `impl<'a> Extend<&'a OsStr> for OsString` - `impl FromIterator for OsString` - `impl<'a> FromIterator<&'a OsStr> for OsString` Because `OsString` is a platform string with no particular semantics, concatenating them together seems acceptable. --- library/std/src/ffi/os_str.rs | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index c9c8f68cd9cce..b7aff83eaf50e 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -5,6 +5,7 @@ use crate::borrow::{Borrow, Cow}; use crate::cmp; use crate::fmt; use crate::hash::{Hash, Hasher}; +use crate::iter::{Extend, FromIterator}; use crate::ops; use crate::rc::Rc; use crate::str::FromStr; @@ -1182,3 +1183,47 @@ impl FromStr for OsString { Ok(OsString::from(s)) } } + +#[stable(feature = "osstring_extend", since = "1.52.0")] +impl Extend for OsString { + #[inline] + fn extend>(&mut self, iter: T) { + for s in iter { + self.push(&s); + } + } +} + +#[stable(feature = "osstring_extend", since = "1.52.0")] +impl<'a> Extend<&'a OsStr> for OsString { + #[inline] + fn extend>(&mut self, iter: T) { + for s in iter { + self.push(s); + } + } +} + +#[stable(feature = "osstring_extend", since = "1.52.0")] +impl FromIterator for OsString { + #[inline] + fn from_iter>(iter: I) -> Self { + let mut buf = Self::new(); + for s in iter { + buf.push(&s); + } + buf + } +} + +#[stable(feature = "osstring_extend", since = "1.52.0")] +impl<'a> FromIterator<&'a OsStr> for OsString { + #[inline] + fn from_iter>(iter: I) -> Self { + let mut buf = Self::new(); + for s in iter { + buf.push(s); + } + buf + } +} From 2fcb8b5c201d22060f1ba46cc2291cacca593e02 Mon Sep 17 00:00:00 2001 From: Ryan Lopopolo Date: Tue, 16 Feb 2021 14:14:59 -0800 Subject: [PATCH 02/14] Optimize FromIterator to reuse the first allocation --- library/std/src/ffi/os_str.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index b7aff83eaf50e..8240aafae74e7 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -1208,11 +1208,18 @@ impl<'a> Extend<&'a OsStr> for OsString { impl FromIterator for OsString { #[inline] fn from_iter>(iter: I) -> Self { - let mut buf = Self::new(); - for s in iter { - buf.push(&s); + let mut iterator = iter.into_iter(); + + // Because we're iterating over `OsString`s, we can avoid at least + // one allocation by getting the first string from the iterator + // and appending to it all the subsequent strings. + match iterator.next() { + None => OsString::new(), + Some(mut buf) => { + buf.extend(iterator); + buf + } } - buf } } From 05ea200213fe30967fff38ebac887c52803aabd5 Mon Sep 17 00:00:00 2001 From: Ryan Lopopolo Date: Wed, 3 Mar 2021 11:52:14 -0800 Subject: [PATCH 03/14] Add impls for iterators of Cow --- library/std/src/ffi/os_str.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 8240aafae74e7..8bdd9a88473f9 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -1204,6 +1204,16 @@ impl<'a> Extend<&'a OsStr> for OsString { } } +#[stable(feature = "osstring_extend", since = "1.52.0")] +impl<'a> Extend> for OsString { + #[inline] + fn extend>>(&mut self, iter: T) { + for s in iter { + self.push(&s); + } + } +} + #[stable(feature = "osstring_extend", since = "1.52.0")] impl FromIterator for OsString { #[inline] @@ -1234,3 +1244,27 @@ impl<'a> FromIterator<&'a OsStr> for OsString { buf } } + +#[stable(feature = "osstring_extend", since = "1.52.0")] +impl<'a> FromIterator> for OsString { + #[inline] + fn from_iter>>(iter: I) -> Self { + let mut iterator = iter.into_iter(); + + // Because we're iterating over `OsString`s, we can avoid at least + // one allocation by getting the first owned string from the iterator + // and appending to it all the subsequent strings. + match iterator.next() { + None => OsString::new(), + Some(Cow::Owned(mut buf)) => { + buf.extend(iterator); + buf + } + Some(Cow::Borrowed(buf)) => { + let mut buf = OsString::from(buf); + buf.extend(iterator); + buf + } + } + } +} From d6b06b8a327ff32d083bc0494cc3195d9f8082d2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 5 Mar 2021 08:43:25 -0800 Subject: [PATCH 04/14] std: Fix a bug on the wasm32-wasi target opening files This commit fixes an issue pointed out in #82758 where LTO changed the behavior of a program. It turns out that LTO was not at fault here, it simply uncovered an existing bug. The bindings to `__wasilibc_find_relpath` assumed that the relative portion of the path returned was always contained within thee input `buf` we passed in. This isn't actually the case, however, and sometimes the relative portion of the path may reference a sub-portion of the input string itself. The fix here is to use the relative path pointer coming out of `__wasilibc_find_relpath` as the source of truth. The `buf` used for local storage is discarded in this function and the relative path is copied out unconditionally. We might be able to get away with some `Cow`-like business or such to avoid the extra allocation, but for now this is probably the easiest patch to fix the original issue. --- library/std/src/sys/wasi/fs.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index bcf7da46b4b07..63c22136273fb 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -650,13 +650,11 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop, PathBuf)> { ); return Err(io::Error::new(io::ErrorKind::Other, msg)); } - let len = CStr::from_ptr(buf.as_ptr().cast()).to_bytes().len(); - buf.set_len(len); - buf.shrink_to_fit(); + let relative = CStr::from_ptr(relative_path).to_bytes().to_vec(); return Ok(( ManuallyDrop::new(WasiFd::from_raw(fd as u32)), - PathBuf::from(OsString::from_vec(buf)), + PathBuf::from(OsString::from_vec(relative)), )); } } From 45229b0777e6791625392529c2c9d8eceac28dbd Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Fri, 5 Mar 2021 09:50:20 -0500 Subject: [PATCH 05/14] Rename `rustdoc` to `rustdoc::all` When rustdoc lints were changed to be tool lints, the `rustdoc` group was removed, leading to spurious warnings like ``` warning: unknown lint: `rustdoc` ``` The lint group still worked when rustdoc ran, since rustdoc added the group itself. This renames the group to `rustdoc::all` for consistency with `clippy::all` and the rest of the rustdoc lints. --- compiler/rustc_lint/src/lib.rs | 1 + src/librustdoc/lint.rs | 4 ++-- src/test/rustdoc-ui/check-fail.rs | 2 +- src/test/rustdoc-ui/check-fail.stderr | 12 +++++----- src/test/rustdoc-ui/check.rs | 2 +- src/test/rustdoc-ui/check.stderr | 16 ++++++------- src/test/rustdoc-ui/lint-group.rs | 2 +- src/test/rustdoc-ui/lint-group.stderr | 24 +++++++++---------- src/test/rustdoc-ui/unknown-renamed-lints.rs | 3 +++ .../rustdoc-ui/unknown-renamed-lints.stderr | 10 ++++++-- src/test/ui/lint/rustdoc-group.rs | 5 ++++ src/test/ui/lint/rustdoc-group.stderr | 10 ++++++++ 12 files changed, 58 insertions(+), 33 deletions(-) create mode 100644 src/test/ui/lint/rustdoc-group.rs create mode 100644 src/test/ui/lint/rustdoc-group.stderr diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 547779dd6856a..94ca0df818b9f 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -343,6 +343,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { "intra_doc_link_resolution_failure", "use `rustdoc::broken_intra_doc_links` instead", ); + store.register_removed("rustdoc", "use `rustdoc::all` instead"); store.register_removed("unknown_features", "replaced by an error"); store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate"); diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs index e8806c1b6d787..754ec53b330f1 100644 --- a/src/librustdoc/lint.rs +++ b/src/librustdoc/lint.rs @@ -175,8 +175,8 @@ crate fn register_lints(_sess: &Session, lint_store: &mut LintStore) { lint_store.register_lints(&**RUSTDOC_LINTS); lint_store.register_group( true, - "rustdoc", - None, + "rustdoc::all", + Some("rustdoc"), RUSTDOC_LINTS.iter().map(|&lint| LintId::of(lint)).collect(), ); for lint in &*RUSTDOC_LINTS { diff --git a/src/test/rustdoc-ui/check-fail.rs b/src/test/rustdoc-ui/check-fail.rs index 291fc112c3407..2355d6a3d6cbc 100644 --- a/src/test/rustdoc-ui/check-fail.rs +++ b/src/test/rustdoc-ui/check-fail.rs @@ -1,7 +1,7 @@ // compile-flags: -Z unstable-options --check #![deny(missing_docs)] -#![deny(rustdoc)] +#![deny(rustdoc::all)] //! ```rust,testharness //~^ ERROR diff --git a/src/test/rustdoc-ui/check-fail.stderr b/src/test/rustdoc-ui/check-fail.stderr index 9f5ccbc6687c2..2758c5490a3d8 100644 --- a/src/test/rustdoc-ui/check-fail.stderr +++ b/src/test/rustdoc-ui/check-fail.stderr @@ -19,9 +19,9 @@ LL | pub fn foo() {} note: the lint level is defined here --> $DIR/check-fail.rs:4:9 | -LL | #![deny(rustdoc)] - | ^^^^^^^ - = note: `#[deny(rustdoc::missing_doc_code_examples)]` implied by `#[deny(rustdoc)]` +LL | #![deny(rustdoc::all)] + | ^^^^^^^^^^^^ + = note: `#[deny(rustdoc::missing_doc_code_examples)]` implied by `#[deny(rustdoc::all)]` error: unknown attribute `testharness`. Did you mean `test_harness`? --> $DIR/check-fail.rs:6:1 @@ -35,9 +35,9 @@ LL | | //! ``` note: the lint level is defined here --> $DIR/check-fail.rs:4:9 | -LL | #![deny(rustdoc)] - | ^^^^^^^ - = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(rustdoc)]` +LL | #![deny(rustdoc::all)] + | ^^^^^^^^^^^^ + = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(rustdoc::all)]` = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function error: unknown attribute `testharness`. Did you mean `test_harness`? diff --git a/src/test/rustdoc-ui/check.rs b/src/test/rustdoc-ui/check.rs index 022c56214d451..65a56e03d9dfc 100644 --- a/src/test/rustdoc-ui/check.rs +++ b/src/test/rustdoc-ui/check.rs @@ -4,7 +4,7 @@ #![warn(missing_docs)] //~^ WARN //~^^ WARN -#![warn(rustdoc)] +#![warn(rustdoc::all)] pub fn foo() {} //~^ WARN diff --git a/src/test/rustdoc-ui/check.stderr b/src/test/rustdoc-ui/check.stderr index e6ba9df9b0555..2e1fc1eca4d6e 100644 --- a/src/test/rustdoc-ui/check.stderr +++ b/src/test/rustdoc-ui/check.stderr @@ -4,7 +4,7 @@ warning: missing documentation for the crate LL | / #![warn(missing_docs)] LL | | LL | | -LL | | #![warn(rustdoc)] +LL | | #![warn(rustdoc::all)] LL | | LL | | pub fn foo() {} | |_______________^ @@ -26,9 +26,9 @@ warning: no documentation found for this crate's top-level module note: the lint level is defined here --> $DIR/check.rs:7:9 | -LL | #![warn(rustdoc)] - | ^^^^^^^ - = note: `#[warn(rustdoc::missing_crate_level_docs)]` implied by `#[warn(rustdoc)]` +LL | #![warn(rustdoc::all)] + | ^^^^^^^^^^^^ + = note: `#[warn(rustdoc::missing_crate_level_docs)]` implied by `#[warn(rustdoc::all)]` = help: The following guide may be of use: https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html @@ -38,7 +38,7 @@ warning: missing code example in this documentation LL | / #![warn(missing_docs)] LL | | LL | | -LL | | #![warn(rustdoc)] +LL | | #![warn(rustdoc::all)] LL | | LL | | pub fn foo() {} | |_______________^ @@ -46,9 +46,9 @@ LL | | pub fn foo() {} note: the lint level is defined here --> $DIR/check.rs:7:9 | -LL | #![warn(rustdoc)] - | ^^^^^^^ - = note: `#[warn(rustdoc::missing_doc_code_examples)]` implied by `#[warn(rustdoc)]` +LL | #![warn(rustdoc::all)] + | ^^^^^^^^^^^^ + = note: `#[warn(rustdoc::missing_doc_code_examples)]` implied by `#[warn(rustdoc::all)]` warning: missing code example in this documentation --> $DIR/check.rs:9:1 diff --git a/src/test/rustdoc-ui/lint-group.rs b/src/test/rustdoc-ui/lint-group.rs index 1446f7f1c1f31..61555a6e68617 100644 --- a/src/test/rustdoc-ui/lint-group.rs +++ b/src/test/rustdoc-ui/lint-group.rs @@ -4,7 +4,7 @@ //! println!("sup"); //! ``` -#![deny(rustdoc)] +#![deny(rustdoc::all)] /// what up, let's make an [error] /// diff --git a/src/test/rustdoc-ui/lint-group.stderr b/src/test/rustdoc-ui/lint-group.stderr index 6f8a20f7d53f0..cc6f03b03ff61 100644 --- a/src/test/rustdoc-ui/lint-group.stderr +++ b/src/test/rustdoc-ui/lint-group.stderr @@ -7,9 +7,9 @@ LL | /// wait, this doesn't have a doctest? note: the lint level is defined here --> $DIR/lint-group.rs:7:9 | -LL | #![deny(rustdoc)] - | ^^^^^^^ - = note: `#[deny(rustdoc::missing_doc_code_examples)]` implied by `#[deny(rustdoc)]` +LL | #![deny(rustdoc::all)] + | ^^^^^^^^^^^^ + = note: `#[deny(rustdoc::missing_doc_code_examples)]` implied by `#[deny(rustdoc::all)]` error: documentation test in private item --> $DIR/lint-group.rs:19:1 @@ -24,9 +24,9 @@ LL | | /// ``` note: the lint level is defined here --> $DIR/lint-group.rs:7:9 | -LL | #![deny(rustdoc)] - | ^^^^^^^ - = note: `#[deny(rustdoc::private_doc_tests)]` implied by `#[deny(rustdoc)]` +LL | #![deny(rustdoc::all)] + | ^^^^^^^^^^^^ + = note: `#[deny(rustdoc::private_doc_tests)]` implied by `#[deny(rustdoc::all)]` error: missing code example in this documentation --> $DIR/lint-group.rs:26:1 @@ -43,9 +43,9 @@ LL | /// what up, let's make an [error] note: the lint level is defined here --> $DIR/lint-group.rs:7:9 | -LL | #![deny(rustdoc)] - | ^^^^^^^ - = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(rustdoc)]` +LL | #![deny(rustdoc::all)] + | ^^^^^^^^^^^^ + = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(rustdoc::all)]` = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` error: unclosed HTML tag `unknown` @@ -57,9 +57,9 @@ LL | /// note: the lint level is defined here --> $DIR/lint-group.rs:7:9 | -LL | #![deny(rustdoc)] - | ^^^^^^^ - = note: `#[deny(rustdoc::invalid_html_tags)]` implied by `#[deny(rustdoc)]` +LL | #![deny(rustdoc::all)] + | ^^^^^^^^^^^^ + = note: `#[deny(rustdoc::invalid_html_tags)]` implied by `#[deny(rustdoc::all)]` error: aborting due to 5 previous errors diff --git a/src/test/rustdoc-ui/unknown-renamed-lints.rs b/src/test/rustdoc-ui/unknown-renamed-lints.rs index d2c78bc477410..9d20cb7d30d55 100644 --- a/src/test/rustdoc-ui/unknown-renamed-lints.rs +++ b/src/test/rustdoc-ui/unknown-renamed-lints.rs @@ -12,6 +12,9 @@ #![deny(non_autolinks)] //~^ ERROR renamed to `rustdoc::non_autolinks` +#![deny(rustdoc)] +//~^ ERROR removed: use `rustdoc::all` instead + // Explicitly don't try to handle this case, it was never valid #![deny(rustdoc::intra_doc_link_resolution_failure)] //~^ ERROR unknown lint diff --git a/src/test/rustdoc-ui/unknown-renamed-lints.stderr b/src/test/rustdoc-ui/unknown-renamed-lints.stderr index 0f31673fb47f2..2036335e85574 100644 --- a/src/test/rustdoc-ui/unknown-renamed-lints.stderr +++ b/src/test/rustdoc-ui/unknown-renamed-lints.stderr @@ -34,13 +34,19 @@ error: lint `non_autolinks` has been renamed to `rustdoc::non_autolinks` LL | #![deny(non_autolinks)] | ^^^^^^^^^^^^^ help: use the new name: `rustdoc::non_autolinks` +error: lint `rustdoc` has been removed: use `rustdoc::all` instead + --> $DIR/unknown-renamed-lints.rs:15:9 + | +LL | #![deny(rustdoc)] + | ^^^^^^^ + error: unknown lint: `rustdoc::intra_doc_link_resolution_failure` - --> $DIR/unknown-renamed-lints.rs:16:9 + --> $DIR/unknown-renamed-lints.rs:19:9 | LL | #![deny(rustdoc::intra_doc_link_resolution_failure)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Compilation failed, aborting rustdoc -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors diff --git a/src/test/ui/lint/rustdoc-group.rs b/src/test/ui/lint/rustdoc-group.rs new file mode 100644 index 0000000000000..130abe4253a13 --- /dev/null +++ b/src/test/ui/lint/rustdoc-group.rs @@ -0,0 +1,5 @@ +// check-pass +// compile-flags: --crate-type lib +#![deny(rustdoc)] +//~^ WARNING removed: use `rustdoc::all` +#![deny(rustdoc::all)] // has no effect when run with rustc directly diff --git a/src/test/ui/lint/rustdoc-group.stderr b/src/test/ui/lint/rustdoc-group.stderr new file mode 100644 index 0000000000000..fddc863ae1e99 --- /dev/null +++ b/src/test/ui/lint/rustdoc-group.stderr @@ -0,0 +1,10 @@ +warning: lint `rustdoc` has been removed: use `rustdoc::all` instead + --> $DIR/rustdoc-group.rs:3:9 + | +LL | #![deny(rustdoc)] + | ^^^^^^^ + | + = note: `#[warn(renamed_and_removed_lints)]` on by default + +warning: 1 warning emitted + From ce2d95cd75adb5f75921536191b4dcfa41be1eff Mon Sep 17 00:00:00 2001 From: Kornel Date: Tue, 9 Mar 2021 18:30:39 +0000 Subject: [PATCH 06/14] Demonstrate best practice for feeding stdin of a child processes It's possible to create a deadlock with stdin/stdout I/O on a single thread: * the child process may fill its stdout buffer, and have to wait for the parent process to read it, * but the parent process may be waiting until its stdin write finishes before reading the stdout. Therefore, the parent process should use separate threads for writing and reading. --- library/std/src/process.rs | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 6480e654c55f0..b199f381b2a28 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -71,11 +71,15 @@ //! .spawn() //! .expect("failed to execute child"); //! -//! { -//! // limited borrow of stdin -//! let stdin = child.stdin.as_mut().expect("failed to get stdin"); +//! // If the child process fills its stdout buffer, it may end up +//! // waiting until the parent reads the stdout, and not be able to +//! // read stdin in the meantime, causing a deadlock. +//! // Writing from another thread ensures that stdout is being read +//! // at the same time, avoiding the problem. +//! let mut stdin = child.stdin.take().expect("failed to get stdin"); +//! std::thread::spawn(move || { //! stdin.write_all(b"test").expect("failed to write to stdin"); -//! } +//! }); //! //! let output = child //! .wait_with_output() @@ -1145,14 +1149,21 @@ impl Stdio { /// .spawn() /// .expect("Failed to spawn child process"); /// - /// { - /// let stdin = child.stdin.as_mut().expect("Failed to open stdin"); + /// let mut stdin = child.stdin.take().expect("Failed to open stdin"); + /// std::thread::spawn(move || { /// stdin.write_all("Hello, world!".as_bytes()).expect("Failed to write to stdin"); - /// } + /// }); /// /// let output = child.wait_with_output().expect("Failed to read stdout"); /// assert_eq!(String::from_utf8_lossy(&output.stdout), "!dlrow ,olleH"); /// ``` + /// + /// Writing more than a pipe buffer's worth of input to stdin without also reading + /// stdout and stderr at the same time may cause a deadlock. + /// This is an issue when running any program that doesn't guarantee that it reads + /// its entire stdin before writing more than a pipe buffer's worth of output. + /// The size of a pipe buffer varies on different targets. + /// #[stable(feature = "process", since = "1.0.0")] pub fn piped() -> Stdio { Stdio(imp::Stdio::MakePipe) From 2fd2796aae18a7e7a736346f344daa56fae37c41 Mon Sep 17 00:00:00 2001 From: csmoe Date: Fri, 5 Mar 2021 13:54:35 +0800 Subject: [PATCH 07/14] add ui testcase for issue 82772 --- compiler/rustc_typeck/src/check/pat.rs | 49 +++++++++++++++++++ .../ui/structs/struct-variant-privacy-xc.rs | 6 ++- .../structs/struct-variant-privacy-xc.stderr | 10 +++- src/test/ui/structs/struct-variant-privacy.rs | 6 ++- .../ui/structs/struct-variant-privacy.stderr | 10 +++- src/test/ui/typeck/issue-82772.rs | 13 +++++ src/test/ui/typeck/issue-82772.stderr | 15 ++++++ 7 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/typeck/issue-82772.rs create mode 100644 src/test/ui/typeck/issue-82772.stderr diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index f8ca916caf127..733f8e3dc9d8f 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1176,6 +1176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut no_field_errors = true; let mut inexistent_fields = vec![]; + let mut invisible_fields = vec![]; // Typecheck each field. for field in fields { let span = field.span; @@ -1191,6 +1192,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field_map .get(&ident) .map(|(i, f)| { + if !f + .vis + .is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx) + { + invisible_fields.push(field.ident); + } self.write_field_index(field.hir_id, *i); self.tcx.check_stability(f.did, Some(pat.hir_id), span); self.field_ty(span, f, substs) @@ -1281,6 +1288,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.error_tuple_variant_index_shorthand(variant, pat, fields) { err.emit(); + } else if !invisible_fields.is_empty() { + let mut err = self.error_invisible_fields( + adt.variant_descr(), + &invisible_fields, + variant, + ); + err.emit(); } } } @@ -1359,6 +1373,41 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .emit(); } + fn error_invisible_fields( + &self, + kind_name: &str, + invisible_fields: &[Ident], + variant: &ty::VariantDef, + ) -> DiagnosticBuilder<'tcx> { + let spans = invisible_fields.iter().map(|ident| ident.span).collect::>(); + let (field_names, t) = if invisible_fields.len() == 1 { + (format!("a field named `{}`", invisible_fields[0]), "is") + } else { + ( + format!( + "fields named {}", + invisible_fields + .iter() + .map(|ident| format!("`{}`", ident)) + .collect::>() + .join(", ") + ), + "are", + ) + }; + let err = struct_span_err!( + self.tcx.sess, + spans, + E0603, + "cannot match on {} of {} `{}`, which {} not accessible in current scope", + field_names, + kind_name, + self.tcx.def_path_str(variant.def_id), + t + ); + err + } + fn error_inexistent_fields( &self, kind_name: &str, diff --git a/src/test/ui/structs/struct-variant-privacy-xc.rs b/src/test/ui/structs/struct-variant-privacy-xc.rs index 10e9639096f0f..bf765be75dd8c 100644 --- a/src/test/ui/structs/struct-variant-privacy-xc.rs +++ b/src/test/ui/structs/struct-variant-privacy-xc.rs @@ -1,9 +1,11 @@ // aux-build:struct_variant_privacy.rs extern crate struct_variant_privacy; -fn f(b: struct_variant_privacy::Bar) { //~ ERROR enum `Bar` is private +fn f(b: struct_variant_privacy::Bar) { + //~^ ERROR enum `Bar` is private match b { - struct_variant_privacy::Bar::Baz { a: _a } => {} //~ ERROR enum `Bar` is private + struct_variant_privacy::Bar::Baz { a: _a } => {} //~ ERROR cannot match on + //~^ ERROR enum `Bar` is private } } diff --git a/src/test/ui/structs/struct-variant-privacy-xc.stderr b/src/test/ui/structs/struct-variant-privacy-xc.stderr index 4e022cef1b2d3..03de40b488ca9 100644 --- a/src/test/ui/structs/struct-variant-privacy-xc.stderr +++ b/src/test/ui/structs/struct-variant-privacy-xc.stderr @@ -11,7 +11,7 @@ LL | enum Bar { | ^^^^^^^^ error[E0603]: enum `Bar` is private - --> $DIR/struct-variant-privacy-xc.rs:6:33 + --> $DIR/struct-variant-privacy-xc.rs:7:33 | LL | struct_variant_privacy::Bar::Baz { a: _a } => {} | ^^^ private enum @@ -22,6 +22,12 @@ note: the enum `Bar` is defined here LL | enum Bar { | ^^^^^^^^ -error: aborting due to 2 previous errors +error[E0603]: cannot match on a field named `a` of variant `struct_variant_privacy::Bar::Baz`, which is not accessible in current scope + --> $DIR/struct-variant-privacy-xc.rs:7:44 + | +LL | struct_variant_privacy::Bar::Baz { a: _a } => {} + | ^ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0603`. diff --git a/src/test/ui/structs/struct-variant-privacy.rs b/src/test/ui/structs/struct-variant-privacy.rs index 8355879e7d94d..7ce8ce9e290c8 100644 --- a/src/test/ui/structs/struct-variant-privacy.rs +++ b/src/test/ui/structs/struct-variant-privacy.rs @@ -1,12 +1,14 @@ mod foo { enum Bar { - Baz { a: isize } + Baz { a: isize }, } } -fn f(b: foo::Bar) { //~ ERROR enum `Bar` is private +fn f(b: foo::Bar) { + //~^ ERROR enum `Bar` is private match b { foo::Bar::Baz { a: _a } => {} //~ ERROR enum `Bar` is private + //~^ ERROR cannot match on } } diff --git a/src/test/ui/structs/struct-variant-privacy.stderr b/src/test/ui/structs/struct-variant-privacy.stderr index a6bc381ff6b38..a69a888553b7a 100644 --- a/src/test/ui/structs/struct-variant-privacy.stderr +++ b/src/test/ui/structs/struct-variant-privacy.stderr @@ -11,7 +11,7 @@ LL | enum Bar { | ^^^^^^^^ error[E0603]: enum `Bar` is private - --> $DIR/struct-variant-privacy.rs:9:14 + --> $DIR/struct-variant-privacy.rs:10:14 | LL | foo::Bar::Baz { a: _a } => {} | ^^^ private enum @@ -22,6 +22,12 @@ note: the enum `Bar` is defined here LL | enum Bar { | ^^^^^^^^ -error: aborting due to 2 previous errors +error[E0603]: cannot match on a field named `a` of variant `Bar::Baz`, which is not accessible in current scope + --> $DIR/struct-variant-privacy.rs:10:25 + | +LL | foo::Bar::Baz { a: _a } => {} + | ^ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0603`. diff --git a/src/test/ui/typeck/issue-82772.rs b/src/test/ui/typeck/issue-82772.rs new file mode 100644 index 0000000000000..62eb5f7a02147 --- /dev/null +++ b/src/test/ui/typeck/issue-82772.rs @@ -0,0 +1,13 @@ +// edition:2018 + +fn main() { + use a::LocalModPrivateStruct; + let Box { 1: _, .. }: Box<()>; //~ ERROR cannot match on + let LocalModPrivateStruct { 1: _, .. } = LocalModPrivateStruct::default(); + //~^ ERROR cannot match on +} + +mod a { + #[derive(Default)] + pub struct LocalModPrivateStruct(u8, u8); +} diff --git a/src/test/ui/typeck/issue-82772.stderr b/src/test/ui/typeck/issue-82772.stderr new file mode 100644 index 0000000000000..5bc6a5aa9e32f --- /dev/null +++ b/src/test/ui/typeck/issue-82772.stderr @@ -0,0 +1,15 @@ +error[E0603]: cannot match on a field named `1` of struct `Box`, which is not accessible in current scope + --> $DIR/issue-82772.rs:5:15 + | +LL | let Box { 1: _, .. }: Box<()>; + | ^ + +error[E0603]: cannot match on a field named `1` of struct `LocalModPrivateStruct`, which is not accessible in current scope + --> $DIR/issue-82772.rs:6:33 + | +LL | let LocalModPrivateStruct { 1: _, .. } = LocalModPrivateStruct::default(); + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. From 77fb6a0f32408925f212d1fb877e900f9736840d Mon Sep 17 00:00:00 2001 From: csmoe Date: Fri, 12 Mar 2021 01:49:27 +0800 Subject: [PATCH 08/14] fix: check before index into generated patterns --- .../src/thir/pattern/deconstruct_pat.rs | 4 +- compiler/rustc_typeck/src/check/pat.rs | 49 ------------------- .../ui/structs/struct-variant-privacy-xc.rs | 3 +- .../structs/struct-variant-privacy-xc.stderr | 8 +-- src/test/ui/structs/struct-variant-privacy.rs | 1 - .../ui/structs/struct-variant-privacy.stderr | 8 +-- src/test/ui/typeck/issue-82772.rs | 10 ++-- src/test/ui/typeck/issue-82772.stderr | 22 ++++++--- 8 files changed, 25 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index 3a67eeff92c31..8c740a7ec155a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -1343,7 +1343,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { match &mut fields { Fields::Vec(pats) => { for (i, pat) in new_pats { - pats[i] = pat + if let Some(p) = pats.get_mut(i) { + *p = pat; + } } } Fields::Filtered { fields, .. } => { diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 733f8e3dc9d8f..f8ca916caf127 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1176,7 +1176,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut no_field_errors = true; let mut inexistent_fields = vec![]; - let mut invisible_fields = vec![]; // Typecheck each field. for field in fields { let span = field.span; @@ -1192,12 +1191,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field_map .get(&ident) .map(|(i, f)| { - if !f - .vis - .is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx) - { - invisible_fields.push(field.ident); - } self.write_field_index(field.hir_id, *i); self.tcx.check_stability(f.did, Some(pat.hir_id), span); self.field_ty(span, f, substs) @@ -1288,13 +1281,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.error_tuple_variant_index_shorthand(variant, pat, fields) { err.emit(); - } else if !invisible_fields.is_empty() { - let mut err = self.error_invisible_fields( - adt.variant_descr(), - &invisible_fields, - variant, - ); - err.emit(); } } } @@ -1373,41 +1359,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .emit(); } - fn error_invisible_fields( - &self, - kind_name: &str, - invisible_fields: &[Ident], - variant: &ty::VariantDef, - ) -> DiagnosticBuilder<'tcx> { - let spans = invisible_fields.iter().map(|ident| ident.span).collect::>(); - let (field_names, t) = if invisible_fields.len() == 1 { - (format!("a field named `{}`", invisible_fields[0]), "is") - } else { - ( - format!( - "fields named {}", - invisible_fields - .iter() - .map(|ident| format!("`{}`", ident)) - .collect::>() - .join(", ") - ), - "are", - ) - }; - let err = struct_span_err!( - self.tcx.sess, - spans, - E0603, - "cannot match on {} of {} `{}`, which {} not accessible in current scope", - field_names, - kind_name, - self.tcx.def_path_str(variant.def_id), - t - ); - err - } - fn error_inexistent_fields( &self, kind_name: &str, diff --git a/src/test/ui/structs/struct-variant-privacy-xc.rs b/src/test/ui/structs/struct-variant-privacy-xc.rs index bf765be75dd8c..763ab952738b7 100644 --- a/src/test/ui/structs/struct-variant-privacy-xc.rs +++ b/src/test/ui/structs/struct-variant-privacy-xc.rs @@ -4,8 +4,7 @@ extern crate struct_variant_privacy; fn f(b: struct_variant_privacy::Bar) { //~^ ERROR enum `Bar` is private match b { - struct_variant_privacy::Bar::Baz { a: _a } => {} //~ ERROR cannot match on - //~^ ERROR enum `Bar` is private + struct_variant_privacy::Bar::Baz { a: _a } => {} //~ ERROR enum `Bar` is private } } diff --git a/src/test/ui/structs/struct-variant-privacy-xc.stderr b/src/test/ui/structs/struct-variant-privacy-xc.stderr index 03de40b488ca9..1c1caaef8b79d 100644 --- a/src/test/ui/structs/struct-variant-privacy-xc.stderr +++ b/src/test/ui/structs/struct-variant-privacy-xc.stderr @@ -22,12 +22,6 @@ note: the enum `Bar` is defined here LL | enum Bar { | ^^^^^^^^ -error[E0603]: cannot match on a field named `a` of variant `struct_variant_privacy::Bar::Baz`, which is not accessible in current scope - --> $DIR/struct-variant-privacy-xc.rs:7:44 - | -LL | struct_variant_privacy::Bar::Baz { a: _a } => {} - | ^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0603`. diff --git a/src/test/ui/structs/struct-variant-privacy.rs b/src/test/ui/structs/struct-variant-privacy.rs index 7ce8ce9e290c8..fcdf9a22baf4b 100644 --- a/src/test/ui/structs/struct-variant-privacy.rs +++ b/src/test/ui/structs/struct-variant-privacy.rs @@ -8,7 +8,6 @@ fn f(b: foo::Bar) { //~^ ERROR enum `Bar` is private match b { foo::Bar::Baz { a: _a } => {} //~ ERROR enum `Bar` is private - //~^ ERROR cannot match on } } diff --git a/src/test/ui/structs/struct-variant-privacy.stderr b/src/test/ui/structs/struct-variant-privacy.stderr index a69a888553b7a..eafd26c716f11 100644 --- a/src/test/ui/structs/struct-variant-privacy.stderr +++ b/src/test/ui/structs/struct-variant-privacy.stderr @@ -22,12 +22,6 @@ note: the enum `Bar` is defined here LL | enum Bar { | ^^^^^^^^ -error[E0603]: cannot match on a field named `a` of variant `Bar::Baz`, which is not accessible in current scope - --> $DIR/struct-variant-privacy.rs:10:25 - | -LL | foo::Bar::Baz { a: _a } => {} - | ^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0603`. diff --git a/src/test/ui/typeck/issue-82772.rs b/src/test/ui/typeck/issue-82772.rs index 62eb5f7a02147..326273bfe9229 100644 --- a/src/test/ui/typeck/issue-82772.rs +++ b/src/test/ui/typeck/issue-82772.rs @@ -1,13 +1,13 @@ // edition:2018 fn main() { - use a::LocalModPrivateStruct; - let Box { 1: _, .. }: Box<()>; //~ ERROR cannot match on - let LocalModPrivateStruct { 1: _, .. } = LocalModPrivateStruct::default(); - //~^ ERROR cannot match on + use a::ModPrivateStruct; + let Box { 0: _, .. }: Box<()>; //~ ERROR field `0` of + let Box { 1: _, .. }: Box<()>; //~ ERROR field `1` of + let ModPrivateStruct { 1: _, .. } = ModPrivateStruct::default(); //~ ERROR field `1` of } mod a { #[derive(Default)] - pub struct LocalModPrivateStruct(u8, u8); + pub struct ModPrivateStruct(u8, u8); } diff --git a/src/test/ui/typeck/issue-82772.stderr b/src/test/ui/typeck/issue-82772.stderr index 5bc6a5aa9e32f..321143cb9683d 100644 --- a/src/test/ui/typeck/issue-82772.stderr +++ b/src/test/ui/typeck/issue-82772.stderr @@ -1,15 +1,21 @@ -error[E0603]: cannot match on a field named `1` of struct `Box`, which is not accessible in current scope +error[E0451]: field `0` of struct `Box` is private --> $DIR/issue-82772.rs:5:15 | +LL | let Box { 0: _, .. }: Box<()>; + | ^^^^ private field + +error[E0451]: field `1` of struct `Box` is private + --> $DIR/issue-82772.rs:6:15 + | LL | let Box { 1: _, .. }: Box<()>; - | ^ + | ^^^^ private field -error[E0603]: cannot match on a field named `1` of struct `LocalModPrivateStruct`, which is not accessible in current scope - --> $DIR/issue-82772.rs:6:33 +error[E0451]: field `1` of struct `ModPrivateStruct` is private + --> $DIR/issue-82772.rs:7:28 | -LL | let LocalModPrivateStruct { 1: _, .. } = LocalModPrivateStruct::default(); - | ^ +LL | let ModPrivateStruct { 1: _, .. } = ModPrivateStruct::default(); + | ^^^^ private field -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0603`. +For more information about this error, try `rustc --explain E0451`. From 1c9d56e9b4dbfd4cbb60b10920d4bef020755b11 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 12 Mar 2021 18:10:17 -0800 Subject: [PATCH 09/14] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 970bc67c37757..32da9eaa5de5b 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 970bc67c3775781b9708c8a36893576b9459c64a +Subproject commit 32da9eaa5de5be241cf8096ca6b749a157194f77 From f2017466259ed99f7ec5ea8273c6e2a6393cf649 Mon Sep 17 00:00:00 2001 From: Sebastian Widua Date: Sat, 13 Mar 2021 01:09:53 +0100 Subject: [PATCH 10/14] Add `reverse` search alias for Iterator::rev() --- library/core/src/iter/traits/iterator.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index e179ce01c417a..f8504e842ee33 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2737,6 +2737,7 @@ pub trait Iterator { /// assert_eq!(iter.next(), None); /// ``` #[inline] + #[doc(alias = "reverse")] #[stable(feature = "rust1", since = "1.0.0")] fn rev(self) -> Rev where From bc8093ed551546730194a2b726dbd39466d199d0 Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Sat, 13 Mar 2021 18:50:43 +0800 Subject: [PATCH 11/14] Fix panic message of `assert_failed_inner` --- library/core/src/panicking.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 12acf5b4329db..3e3e96fcd7f78 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -154,7 +154,7 @@ fn assert_failed_inner( Some(args) => panic!( r#"assertion failed: `(left {} right)` left: `{:?}`, - right: `{:?}: {}`"#, + right: `{:?}`: {}"#, op, left, right, args ), None => panic!( From 7ecb5d86014f4da127c3d17c4b9fea3b344e7cde Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Sat, 13 Mar 2021 19:14:57 +0800 Subject: [PATCH 12/14] Add regression tests --- src/test/ui/macros/assert-eq-macro-msg.rs | 9 +++++++++ src/test/ui/macros/assert-matches-macro-msg.rs | 11 +++++++++++ src/test/ui/macros/assert-ne-macro-msg.rs | 9 +++++++++ 3 files changed, 29 insertions(+) create mode 100644 src/test/ui/macros/assert-eq-macro-msg.rs create mode 100644 src/test/ui/macros/assert-matches-macro-msg.rs create mode 100644 src/test/ui/macros/assert-ne-macro-msg.rs diff --git a/src/test/ui/macros/assert-eq-macro-msg.rs b/src/test/ui/macros/assert-eq-macro-msg.rs new file mode 100644 index 0000000000000..accbd2d1e7f50 --- /dev/null +++ b/src/test/ui/macros/assert-eq-macro-msg.rs @@ -0,0 +1,9 @@ +// run-fail +// error-pattern:panicked at 'assertion failed: `(left == right)` +// error-pattern: left: `2` +// error-pattern:right: `3`: 1 + 1 definitely should be 3' +// ignore-emscripten no processes + +fn main() { + assert_eq!(1 + 1, 3, "1 + 1 definitely should be 3"); +} diff --git a/src/test/ui/macros/assert-matches-macro-msg.rs b/src/test/ui/macros/assert-matches-macro-msg.rs new file mode 100644 index 0000000000000..43be9532f5d1c --- /dev/null +++ b/src/test/ui/macros/assert-matches-macro-msg.rs @@ -0,0 +1,11 @@ +// run-fail +// error-pattern:panicked at 'assertion failed: `(left matches right)` +// error-pattern: left: `2` +// error-pattern:right: `3`: 1 + 1 definitely should be 3' +// ignore-emscripten no processes + +#![feature(assert_matches)] + +fn main() { + assert_matches!(1 + 1, 3, "1 + 1 definitely should be 3"); +} diff --git a/src/test/ui/macros/assert-ne-macro-msg.rs b/src/test/ui/macros/assert-ne-macro-msg.rs new file mode 100644 index 0000000000000..fc0472b99b428 --- /dev/null +++ b/src/test/ui/macros/assert-ne-macro-msg.rs @@ -0,0 +1,9 @@ +// run-fail +// error-pattern:panicked at 'assertion failed: `(left != right)` +// error-pattern: left: `2` +// error-pattern:right: `2`: 1 + 1 definitely should not be 2' +// ignore-emscripten no processes + +fn main() { + assert_ne!(1 + 1, 2, "1 + 1 definitely should not be 2"); +} From 8fd2f0c81f95eeb9440369ac046124d8dbd85a31 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 28 Jan 2021 00:51:31 -0800 Subject: [PATCH 13/14] Add documentation about formatting `Duration` values Explain why Duration has a Debug impl but not a Display impl, and mention the use of Unicode. --- library/core/src/time.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 88b4e2a2436e7..b9ee931eeecfd 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -48,6 +48,17 @@ const MICROS_PER_SEC: u64 = 1_000_000; /// /// let ten_millis = Duration::from_millis(10); /// ``` +/// +/// # Formatting `Duration` values +/// +/// `Duration` intentionally does not have a `Display` impl, as there are a +/// variety of ways to format spans of time for human readability. `Duration` +/// provides a `Debug` impl that shows the full precision of the value. +/// +/// The `Debug` output uses the non-ASCII "µs" suffix for microseconds. If your +/// program output may appear in contexts that cannot rely on full Unicode +/// compatibility, you may wish to format `Duration` objects yourself or use a +/// crate to do so. #[stable(feature = "duration", since = "1.3.0")] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct Duration { From 8164a74eefd4f6b098b5f86c8c4205edf6382f54 Mon Sep 17 00:00:00 2001 From: Camelid Date: Sat, 27 Feb 2021 19:36:37 -0800 Subject: [PATCH 14/14] Document `everybody_loops` --- compiler/rustc_interface/src/util.rs | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 0a30eda1ec406..341cfa4790027 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -712,16 +712,24 @@ pub fn non_durable_rename(src: &Path, dst: &Path) -> std::io::Result<()> { std::fs::rename(src, dst) } -// Note: Also used by librustdoc, see PR #43348. Consider moving this struct elsewhere. -// -// FIXME: Currently the `everybody_loops` transformation is not applied to: -// * `const fn`, due to issue #43636 that `loop` is not supported for const evaluation. We are -// waiting for miri to fix that. -// * `impl Trait`, due to issue #43869 that functions returning impl Trait cannot be diverging. -// Solving this may require `!` to implement every trait, which relies on the an even more -// ambitious form of the closed RFC #1637. See also [#34511]. -// -// [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401 +/// Replaces function bodies with `loop {}` (an infinite loop). This gets rid of +/// all semantic errors in the body while still satisfying the return type, +/// except in certain cases, see below for more. +/// +/// This pass is known as `everybody_loops`. Very punny. +/// +/// As of March 2021, `everybody_loops` is only used for the +/// `-Z unpretty=everybody_loops` debugging option. +/// +/// FIXME: Currently the `everybody_loops` transformation is not applied to: +/// * `const fn`; support could be added, but hasn't. Originally `const fn` +/// was skipped due to issue #43636 that `loop` was not supported for +/// const evaluation. +/// * `impl Trait`, due to issue #43869 that functions returning impl Trait cannot be diverging. +/// Solving this may require `!` to implement every trait, which relies on the an even more +/// ambitious form of the closed RFC #1637. See also [#34511]. +/// +/// [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401 pub struct ReplaceBodyWithLoop<'a, 'b> { within_static_or_const: bool, nested_blocks: Option>,