From cbe428d8cb60f901cae2c99a5aff0f563b142681 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Thu, 18 Aug 2022 20:23:01 -0700 Subject: [PATCH 01/20] use `confstr(_CS_DARWIN_USER_TEMP_DIR, ...)` as a `TMPDIR` fallback on darwin --- library/std/src/env.rs | 15 ++++- library/std/src/sys/pal/unix/os.rs | 76 ++++++++++++++++++++++-- library/std/src/sys/pal/unix/os/tests.rs | 25 ++++++++ 3 files changed, 109 insertions(+), 7 deletions(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 97a1b846a91a4..5a2deada6c355 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -653,19 +653,28 @@ pub fn home_dir() -> Option { /// may result in "insecure temporary file" security vulnerabilities. Consider /// using a crate that securely creates temporary files or directories. /// +/// Note that the returned value may be a symbolic link, not a directory. +/// /// # Platform-specific behavior /// /// On Unix, returns the value of the `TMPDIR` environment variable if it is -/// set, otherwise for non-Android it returns `/tmp`. On Android, since there -/// is no global temporary folder (it is usually allocated per-app), it returns -/// `/data/local/tmp`. +/// set, otherwise the value is OS-specific: +/// - On Android, there is no global temporary folder (it is usually allocated +/// per-app), it returns `/data/local/tmp`. +/// - On Darwin-based OSes (macOS, iOS, etc) it returns the directory provided +/// by `confstr(_CS_DARWIN_USER_TEMP_DIR, ...)`, as recommended by [Apple's +/// security guidelines][appledoc]. +/// - On all other unix-based OSes, it returns `/tmp`. +/// /// On Windows, the behavior is equivalent to that of [`GetTempPath2`][GetTempPath2] / /// [`GetTempPath`][GetTempPath], which this function uses internally. +/// /// Note that, this [may change in the future][changes]. /// /// [changes]: io#platform-specific-behavior /// [GetTempPath2]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a /// [GetTempPath]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha +/// [appledoc]: https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html#//apple_ref/doc/uid/TP40002585-SW10 /// /// ```no_run /// use std::env; diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index f983d174ed61c..7db037d02eba0 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -698,12 +698,80 @@ pub fn page_size() -> usize { unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize } } +// Returns the value for [`confstr(key, ...)`][posix_confstr]. Currently only +// used on Darwin, but should work on any unix (in case we need to get +// `_CS_PATH` or `_CS_V[67]_ENV` in the future). +// +// [posix_confstr]: +// https://pubs.opengroup.org/onlinepubs/9699919799/functions/confstr.html +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] +fn confstr(key: c_int, size_hint: Option) -> io::Result { + let mut buf: Vec = Vec::new(); + let mut bytes_needed_including_nul = size_hint + .unwrap_or_else(|| { + // Treat "None" as "do an extra call to get the length". In theory + // we could move this into the loop below, but it's hard to do given + // that it isn't 100% clear if it's legal to pass 0 for `len` when + // the buffer isn't null. + unsafe { libc::confstr(key, core::ptr::null_mut(), 0) } + }) + .max(1); + // If the value returned by `confstr` is greater than the len passed into + // it, then the value was truncated, meaning we need to retry. Note that + // while `confstr` results don't seem to change for a process, it's unclear + // if this is guaranteed anywhere, so looping does seem required. + while bytes_needed_including_nul > buf.capacity() { + // We write into the spare capacity of `buf`. This lets us avoid + // changing buf's `len`, which both simplifies `reserve` computation, + // allows working with `Vec` instead of `Vec>`, and + // may avoid a copy, since the Vec knows that none of the bytes are needed + // when reallocating (well, in theory anyway). + buf.reserve(bytes_needed_including_nul); + // `confstr` returns + // - 0 in the case of errors: we break and return an error. + // - The number of bytes written, iff the provided buffer is enough to + // hold the entire value: we break and return the data in `buf`. + // - Otherwise, the number of bytes needed (including nul): we go + // through the loop again. + bytes_needed_including_nul = + unsafe { libc::confstr(key, buf.as_mut_ptr().cast::(), buf.capacity()) }; + } + // `confstr` returns 0 in the case of an error. + if bytes_needed_including_nul == 0 { + return Err(io::Error::last_os_error()); + } + // Safety: `confstr(..., buf.as_mut_ptr(), buf.capacity())` returned a + // non-zero value, meaning `bytes_needed_including_nul` bytes were + // initialized. + unsafe { + buf.set_len(bytes_needed_including_nul); + // Remove the NUL-terminator. + let last_byte = buf.pop(); + // ... and smoke-check that it *was* a NUL-terminator. + assert_eq!(last_byte, Some(0), "`confstr` provided a string which wasn't nul-terminated"); + }; + Ok(OsString::from_vec(buf)) +} + +#[cfg(target_vendor = "apple")] +fn darwin_temp_dir() -> PathBuf { + confstr(libc::_CS_DARWIN_USER_TEMP_DIR, Some(64)).map(PathBuf::from).unwrap_or_else(|_| { + // It failed for whatever reason (there are several possible reasons), + // so return the global one. + PathBuf::from("/tmp") + }) +} + pub fn temp_dir() -> PathBuf { crate::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| { - if cfg!(target_os = "android") { - PathBuf::from("/data/local/tmp") - } else { - PathBuf::from("/tmp") + cfg_if::cfg_if! { + if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] { + darwin_temp_dir() + } else if #[cfg(target_os = "android")] { + PathBuf::from("/data/local/tmp") + } else { + PathBuf::from("/tmp") + } } }) } diff --git a/library/std/src/sys/pal/unix/os/tests.rs b/library/std/src/sys/pal/unix/os/tests.rs index efc29955b05fe..ab9742fc677e9 100644 --- a/library/std/src/sys/pal/unix/os/tests.rs +++ b/library/std/src/sys/pal/unix/os/tests.rs @@ -21,3 +21,28 @@ fn test_parse_glibc_version() { assert_eq!(parsed, super::parse_glibc_version(version_str)); } } + +// Smoke check `confstr`, do it for several hint values, to ensure our resizing +// logic is correct. +#[test] +#[cfg(target_os = "macos")] +fn test_confstr() { + for key in [libc::_CS_DARWIN_USER_TEMP_DIR, libc::_CS_PATH] { + let value_nohint = super::confstr(key, None).unwrap_or_else(|e| { + panic!("confstr({key}, None) failed: {e:?}"); + }); + let end = (value_nohint.len() + 1) * 2; + for hint in 0..end { + assert_eq!( + super::confstr(key, Some(hint)).as_deref().ok(), + Some(&*value_nohint), + "confstr({key}, Some({hint})) failed", + ); + } + } + // Smoke check that we don't loop forever or something if the input was not valid. + for hint in [None, Some(0), Some(1)] { + let hopefully_invalid = 123456789_i32; + assert!(super::confstr(hopefully_invalid, hint).is_err()); + } +} From 6d075dc4d7335a239f887b28a630bdc9aa08e140 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 18:41:55 +0200 Subject: [PATCH 02/20] Prefer `target_vendor = "apple"` on confstr --- library/std/src/sys/pal/unix/os.rs | 4 ++-- library/std/src/sys/pal/unix/os/tests.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 7db037d02eba0..9750c32eed5e5 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -704,7 +704,7 @@ pub fn page_size() -> usize { // // [posix_confstr]: // https://pubs.opengroup.org/onlinepubs/9699919799/functions/confstr.html -#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] +#[cfg(target_vendor = "apple")] fn confstr(key: c_int, size_hint: Option) -> io::Result { let mut buf: Vec = Vec::new(); let mut bytes_needed_including_nul = size_hint @@ -765,7 +765,7 @@ fn darwin_temp_dir() -> PathBuf { pub fn temp_dir() -> PathBuf { crate::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| { cfg_if::cfg_if! { - if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] { + if #[cfg(target_vendor = "apple")] { darwin_temp_dir() } else if #[cfg(target_os = "android")] { PathBuf::from("/data/local/tmp") diff --git a/library/std/src/sys/pal/unix/os/tests.rs b/library/std/src/sys/pal/unix/os/tests.rs index ab9742fc677e9..a84086037ce0b 100644 --- a/library/std/src/sys/pal/unix/os/tests.rs +++ b/library/std/src/sys/pal/unix/os/tests.rs @@ -25,7 +25,7 @@ fn test_parse_glibc_version() { // Smoke check `confstr`, do it for several hint values, to ensure our resizing // logic is correct. #[test] -#[cfg(target_os = "macos")] +#[cfg(target_vendor = "apple")] fn test_confstr() { for key in [libc::_CS_DARWIN_USER_TEMP_DIR, libc::_CS_PATH] { let value_nohint = super::confstr(key, None).unwrap_or_else(|e| { From b62ee10e5448a077e67e46f6907a4a04415895a8 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 18:57:44 +0200 Subject: [PATCH 03/20] Use with_capacity(0) because we're reading the capacity later on --- library/std/src/sys/pal/unix/os.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 9750c32eed5e5..d26a1bdef74b4 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -706,7 +706,7 @@ pub fn page_size() -> usize { // https://pubs.opengroup.org/onlinepubs/9699919799/functions/confstr.html #[cfg(target_vendor = "apple")] fn confstr(key: c_int, size_hint: Option) -> io::Result { - let mut buf: Vec = Vec::new(); + let mut buf: Vec = Vec::with_capacity(0); let mut bytes_needed_including_nul = size_hint .unwrap_or_else(|| { // Treat "None" as "do an extra call to get the length". In theory From e32a118e6cec5cfbd3552559787c98f6371d5ac1 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Mon, 4 Nov 2024 11:21:22 +0000 Subject: [PATCH 04/20] btree: don't leak value if destructor of key panics --- .../alloc/src/collections/btree/map/tests.rs | 48 +++++++++++++++++++ library/alloc/src/collections/btree/node.rs | 18 ++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index db16d82be7dcc..5975134382e7d 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -2270,6 +2270,54 @@ fn test_into_iter_drop_leak_height_0() { assert_eq!(e.dropped(), 1); } +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn test_into_iter_drop_leak_kv_panic_in_key() { + let a_k = CrashTestDummy::new(0); + let a_v = CrashTestDummy::new(1); + let b_k = CrashTestDummy::new(2); + let b_v = CrashTestDummy::new(3); + let c_k = CrashTestDummy::new(4); + let c_v = CrashTestDummy::new(5); + let mut map = BTreeMap::new(); + map.insert(a_k.spawn(Panic::Never), a_v.spawn(Panic::Never)); + map.insert(b_k.spawn(Panic::InDrop), b_v.spawn(Panic::Never)); + map.insert(c_k.spawn(Panic::Never), c_v.spawn(Panic::Never)); + + catch_unwind(move || drop(map.into_iter())).unwrap_err(); + + assert_eq!(a_k.dropped(), 1); + assert_eq!(a_v.dropped(), 1); + assert_eq!(b_k.dropped(), 1); + assert_eq!(b_v.dropped(), 1); + assert_eq!(c_k.dropped(), 1); + assert_eq!(c_v.dropped(), 1); +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn test_into_iter_drop_leak_kv_panic_in_val() { + let a_k = CrashTestDummy::new(0); + let a_v = CrashTestDummy::new(1); + let b_k = CrashTestDummy::new(2); + let b_v = CrashTestDummy::new(3); + let c_k = CrashTestDummy::new(4); + let c_v = CrashTestDummy::new(5); + let mut map = BTreeMap::new(); + map.insert(a_k.spawn(Panic::Never), a_v.spawn(Panic::Never)); + map.insert(b_k.spawn(Panic::Never), b_v.spawn(Panic::InDrop)); + map.insert(c_k.spawn(Panic::Never), c_v.spawn(Panic::Never)); + + catch_unwind(move || drop(map.into_iter())).unwrap_err(); + + assert_eq!(a_k.dropped(), 1); + assert_eq!(a_v.dropped(), 1); + assert_eq!(b_k.dropped(), 1); + assert_eq!(b_v.dropped(), 1); + assert_eq!(c_k.dropped(), 1); + assert_eq!(c_v.dropped(), 1); +} + #[test] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_into_iter_drop_leak_height_1() { diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 2a853ef421629..64a13bb6a0b3a 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -1173,11 +1173,25 @@ impl Handle, marker::KV> /// The node that the handle refers to must not yet have been deallocated. #[inline] pub unsafe fn drop_key_val(mut self) { + // Run the destructor of the value even if the destructor of the key panics. + struct Dropper<'a, T>(&'a mut MaybeUninit); + impl Drop for Dropper<'_, T> { + #[inline] + fn drop(&mut self) { + unsafe { + self.0.assume_init_drop(); + } + } + } + debug_assert!(self.idx < self.node.len()); let leaf = self.node.as_leaf_dying(); unsafe { - leaf.keys.get_unchecked_mut(self.idx).assume_init_drop(); - leaf.vals.get_unchecked_mut(self.idx).assume_init_drop(); + let key = leaf.keys.get_unchecked_mut(self.idx); + let val = leaf.vals.get_unchecked_mut(self.idx); + let _guard = Dropper(val); + key.assume_init_drop(); + // dropping the guard will drop the value } } } From 0a619dd8ff56f53ec1b85b7e52ad68dc0e2c2e96 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 18 Nov 2024 17:43:28 +1100 Subject: [PATCH 05/20] Rename `parse_no_flag` to `parse_no_value` The old name and comment suggest that this parser is only used for options beginning with `no-`, which is mostly true but not entirely true. --- compiler/rustc_session/src/options.rs | 40 +++++++++++++++------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index f485e8cace54d..f3d564305b63a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -358,7 +358,7 @@ fn build_options( #[allow(non_upper_case_globals)] mod desc { - pub(crate) const parse_no_flag: &str = "no value"; + pub(crate) const parse_no_value: &str = "no value"; pub(crate) const parse_bool: &str = "one of: `y`, `yes`, `on`, `true`, `n`, `no`, `off` or `false`"; pub(crate) const parse_opt_bool: &str = parse_bool; @@ -462,14 +462,18 @@ pub mod parse { pub(crate) use super::*; pub(crate) const MAX_THREADS_CAP: usize = 256; - /// This is for boolean options that don't take a value and start with - /// `no-`. This style of option is deprecated. - pub(crate) fn parse_no_flag(slot: &mut bool, v: Option<&str>) -> bool { + /// This is for boolean options that don't take a value, and are true simply + /// by existing on the command-line. + /// + /// This style of option is deprecated, and is mainly used by old options + /// beginning with `no-`. + pub(crate) fn parse_no_value(slot: &mut bool, v: Option<&str>) -> bool { match v { None => { *slot = true; true } + // Trying to specify a value is always forbidden. Some(_) => false, } } @@ -1609,16 +1613,16 @@ options! { "perform LLVM link-time optimizations"), metadata: Vec = (Vec::new(), parse_list, [TRACKED], "metadata to mangle symbol names with"), - no_prepopulate_passes: bool = (false, parse_no_flag, [TRACKED], + no_prepopulate_passes: bool = (false, parse_no_value, [TRACKED], "give an empty list of passes to the pass manager"), no_redzone: Option = (None, parse_opt_bool, [TRACKED], "disable the use of the redzone"), #[rustc_lint_opt_deny_field_access("documented to do nothing")] - no_stack_check: bool = (false, parse_no_flag, [UNTRACKED], + no_stack_check: bool = (false, parse_no_value, [UNTRACKED], "this option is deprecated and does nothing"), - no_vectorize_loops: bool = (false, parse_no_flag, [TRACKED], + no_vectorize_loops: bool = (false, parse_no_value, [TRACKED], "disable loop vectorization optimization passes"), - no_vectorize_slp: bool = (false, parse_no_flag, [TRACKED], + no_vectorize_slp: bool = (false, parse_no_value, [TRACKED], "disable LLVM's SLP vectorization pass"), opt_level: String = ("0".to_string(), parse_string, [TRACKED], "optimization level (0-3, s, or z; default: 0)"), @@ -1917,25 +1921,25 @@ options! { "dump facts from NLL analysis into side files (default: no)"), nll_facts_dir: String = ("nll-facts".to_string(), parse_string, [UNTRACKED], "the directory the NLL facts are dumped into (default: `nll-facts`)"), - no_analysis: bool = (false, parse_no_flag, [UNTRACKED], + no_analysis: bool = (false, parse_no_value, [UNTRACKED], "parse and expand the source, but run no analysis"), - no_codegen: bool = (false, parse_no_flag, [TRACKED_NO_CRATE_HASH], + no_codegen: bool = (false, parse_no_value, [TRACKED_NO_CRATE_HASH], "run all passes except codegen; no output"), - no_generate_arange_section: bool = (false, parse_no_flag, [TRACKED], + no_generate_arange_section: bool = (false, parse_no_value, [TRACKED], "omit DWARF address ranges that give faster lookups"), no_implied_bounds_compat: bool = (false, parse_bool, [TRACKED], "disable the compatibility version of the `implied_bounds_ty` query"), - no_jump_tables: bool = (false, parse_no_flag, [TRACKED], + no_jump_tables: bool = (false, parse_no_value, [TRACKED], "disable the jump tables and lookup tables that can be generated from a switch case lowering"), - no_leak_check: bool = (false, parse_no_flag, [UNTRACKED], + no_leak_check: bool = (false, parse_no_value, [UNTRACKED], "disable the 'leak check' for subtyping; unsound, but useful for tests"), - no_link: bool = (false, parse_no_flag, [TRACKED], + no_link: bool = (false, parse_no_value, [TRACKED], "compile without linking"), - no_parallel_backend: bool = (false, parse_no_flag, [UNTRACKED], + no_parallel_backend: bool = (false, parse_no_value, [UNTRACKED], "run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"), - no_profiler_runtime: bool = (false, parse_no_flag, [TRACKED], + no_profiler_runtime: bool = (false, parse_no_value, [TRACKED], "prevent automatic injection of the profiler_builtins crate"), - no_trait_vptr: bool = (false, parse_no_flag, [TRACKED], + no_trait_vptr: bool = (false, parse_no_value, [TRACKED], "disable generation of trait vptr in vtable for upcasting"), no_unique_section_names: bool = (false, parse_bool, [TRACKED], "do not use unique names for text and data sections when -Z function-sections is used"), @@ -1993,7 +1997,7 @@ options! { proc_macro_execution_strategy: ProcMacroExecutionStrategy = (ProcMacroExecutionStrategy::SameThread, parse_proc_macro_execution_strategy, [UNTRACKED], "how to run proc-macro code (default: same-thread)"), - profile_closures: bool = (false, parse_no_flag, [UNTRACKED], + profile_closures: bool = (false, parse_no_value, [UNTRACKED], "profile size of closures"), profile_sample_use: Option = (None, parse_opt_pathbuf, [TRACKED], "use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)"), From 660246bc762c426a9f46a212ee4b35b0d54256c1 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 18 Nov 2024 17:36:45 +1100 Subject: [PATCH 06/20] Don't allow `-Zunstable-options` to take a value Passing an explicit boolean value (`on`, `off` etc.) appears to work, but actually puts the compiler into an unintended state where unstable _options_ are still forbidden, but unstable values of _some_ stable options are allowed. --- compiler/rustc_session/src/options.rs | 8 +++++++- tests/ui/codemap_tests/huge_multispan_highlight.rs | 2 +- tests/ui/diagnostic-width/E0271.rs | 2 +- tests/ui/diagnostic-width/flag-human.rs | 2 +- tests/ui/diagnostic-width/long-E0308.rs | 2 +- .../non-1-width-unicode-multiline-label.rs | 2 +- tests/ui/diagnostic-width/non-whitespace-trimming-2.rs | 2 +- tests/ui/error-emitter/unicode-output.rs | 2 +- 8 files changed, 14 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index f3d564305b63a..d2ae83cada8fd 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2171,8 +2171,14 @@ written to standard error output)"), "enable unsound and buggy MIR optimizations (default: no)"), /// This name is kind of confusing: Most unstable options enable something themselves, while /// this just allows "normal" options to be feature-gated. + /// + /// The main check for `-Zunstable-options` takes place separately from the + /// usual parsing of `-Z` options (see [`crate::config::nightly_options`]), + /// so this boolean value is mostly used for enabling unstable _values_ of + /// stable options. That separate check doesn't handle boolean values, so + /// to avoid an inconsistent state we also forbid them here. #[rustc_lint_opt_deny_field_access("use `Session::unstable_options` instead of this field")] - unstable_options: bool = (false, parse_bool, [UNTRACKED], + unstable_options: bool = (false, parse_no_value, [UNTRACKED], "adds unstable command line options to rustc interface (default: no)"), use_ctors_section: Option = (None, parse_opt_bool, [TRACKED], "use legacy .ctors section for initializers rather than .init_array"), diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.rs b/tests/ui/codemap_tests/huge_multispan_highlight.rs index 7d7b757082350..6f6834b01bd61 100644 --- a/tests/ui/codemap_tests/huge_multispan_highlight.rs +++ b/tests/ui/codemap_tests/huge_multispan_highlight.rs @@ -1,7 +1,7 @@ //@ revisions: ascii unicode //@ compile-flags: --color=always //@[ascii] compile-flags: --error-format=human -//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode +//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode //@ ignore-windows fn main() { let _ = match true { diff --git a/tests/ui/diagnostic-width/E0271.rs b/tests/ui/diagnostic-width/E0271.rs index ce41ad2952bc9..dedae4365e889 100644 --- a/tests/ui/diagnostic-width/E0271.rs +++ b/tests/ui/diagnostic-width/E0271.rs @@ -1,6 +1,6 @@ //@ revisions: ascii unicode //@[ascii] compile-flags: --diagnostic-width=40 -//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode --diagnostic-width=40 +//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode --diagnostic-width=40 //@ normalize-stderr-test: "long-type-\d+" -> "long-type-hash" trait Future { type Error; diff --git a/tests/ui/diagnostic-width/flag-human.rs b/tests/ui/diagnostic-width/flag-human.rs index 1af4165914164..8e656293b4102 100644 --- a/tests/ui/diagnostic-width/flag-human.rs +++ b/tests/ui/diagnostic-width/flag-human.rs @@ -1,6 +1,6 @@ //@ revisions: ascii unicode //@[ascii] compile-flags: --diagnostic-width=20 -//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode --diagnostic-width=20 +//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode --diagnostic-width=20 // This test checks that `-Z output-width` effects the human error output by restricting it to an // arbitrarily low value so that the effect is visible. diff --git a/tests/ui/diagnostic-width/long-E0308.rs b/tests/ui/diagnostic-width/long-E0308.rs index 73f81f5872a64..695852f83ac0a 100644 --- a/tests/ui/diagnostic-width/long-E0308.rs +++ b/tests/ui/diagnostic-width/long-E0308.rs @@ -1,6 +1,6 @@ //@ revisions: ascii unicode //@[ascii] compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes -//@[unicode] compile-flags: -Zunstable-options=yes --json=diagnostic-unicode --diagnostic-width=60 -Zwrite-long-types-to-disk=yes +//@[unicode] compile-flags: -Zunstable-options --json=diagnostic-unicode --diagnostic-width=60 -Zwrite-long-types-to-disk=yes //@ normalize-stderr-test: "long-type-\d+" -> "long-type-hash" mod a { diff --git a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs index 61c4b31e03a62..e630db8ba42a2 100644 --- a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs +++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs @@ -1,5 +1,5 @@ //@ revisions: ascii unicode -//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode +//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode // ignore-tidy-linelength fn main() { diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs b/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs index 283506bd6c90d..de2f42a4a7292 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs @@ -1,5 +1,5 @@ //@ revisions: ascii unicode -//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode +//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode // ignore-tidy-linelength fn main() { diff --git a/tests/ui/error-emitter/unicode-output.rs b/tests/ui/error-emitter/unicode-output.rs index ba6db37b66c22..5c083c4e57508 100644 --- a/tests/ui/error-emitter/unicode-output.rs +++ b/tests/ui/error-emitter/unicode-output.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zunstable-options=yes --error-format=human-unicode --color=always +//@ compile-flags: -Zunstable-options --error-format=human-unicode --color=always //@ edition:2018 //@ only-linux From d318878c5fb164a29bbd7c12dafd564dfec16c8b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 20 Nov 2024 14:31:27 +0100 Subject: [PATCH 07/20] Reduce integer `Display` implementation size --- library/core/src/fmt/num.rs | 82 ++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index f2d7e0f481e76..01b5d46a8f696 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -199,35 +199,45 @@ static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\ 8081828384858687888990919293949596979899"; macro_rules! impl_Display { - ($($t:ident $(as $positive:ident)? named $name:ident,)* ; as $u:ident via $conv_fn:ident named $gen_name:ident) => { + ($($signed:ident, $unsigned:ident,)* ; as $u:ident via $conv_fn:ident named $gen_name:ident) => { $( #[stable(feature = "rust1", since = "1.0.0")] - impl fmt::Display for $t { + impl fmt::Display for $unsigned { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // If it's a signed integer. - $( - let is_nonnegative = *self >= 0; + #[cfg(not(feature = "optimize_for_size"))] + { + self._fmt(true, f) + } + #[cfg(feature = "optimize_for_size")] + { + $gen_name(self.$conv_fn(), true, f) + } + } + } + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::Display for $signed { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let is_nonnegative = *self >= 0; + + if !is_nonnegative { #[cfg(not(feature = "optimize_for_size"))] { - if !is_nonnegative { - // convert the negative num to positive by summing 1 to its 2s complement - return (!self as $positive).wrapping_add(1)._fmt(false, f); - } + // convert the negative num to positive by summing 1 to its 2s complement + return (!self as $unsigned).wrapping_add(1)._fmt(false, f); } #[cfg(feature = "optimize_for_size")] { - if !is_nonnegative { - // convert the negative num to positive by summing 1 to its 2s complement - return $gen_name((!self.$conv_fn()).wrapping_add(1), false, f); - } + // convert the negative num to positive by summing 1 to its 2s complement + return $gen_name((!self.$conv_fn()).wrapping_add(1), false, f); } - )? + } + // If it's a positive integer. #[cfg(not(feature = "optimize_for_size"))] { - self._fmt(true, f) + (*self as $unsigned)._fmt(true, f) } #[cfg(feature = "optimize_for_size")] { @@ -237,9 +247,9 @@ macro_rules! impl_Display { } #[cfg(not(feature = "optimize_for_size"))] - impl $t { - fn _fmt(mut self: $t, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { - const SIZE: usize = $t::MAX.ilog(10) as usize + 1; + impl $unsigned { + fn _fmt(mut self, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { + const SIZE: usize = $unsigned::MAX.ilog(10) as usize + 1; let mut buf = [MaybeUninit::::uninit(); SIZE]; let mut curr = SIZE; let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); @@ -258,7 +268,7 @@ macro_rules! impl_Display { #[allow(unused_comparisons)] // This block will be removed for smaller types at compile time and in the worst // case, it will prevent to have the `10000` literal to overflow for `i8` and `u8`. - if core::mem::size_of::<$t>() >= 2 { + if core::mem::size_of::<$unsigned>() >= 2 { // eagerly decode 4 characters at a time while self >= 10000 { let rem = (self % 10000) as usize; @@ -312,8 +322,8 @@ macro_rules! impl_Display { #[cfg(feature = "optimize_for_size")] fn $gen_name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // 2^128 is about 3*10^38, so 39 gives an extra byte of space - let mut buf = [MaybeUninit::::uninit(); 39]; + const SIZE: usize = $u::MAX.ilog(10) as usize + 1; + let mut buf = [MaybeUninit::::uninit(); SIZE]; let mut curr = buf.len(); let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); @@ -523,16 +533,11 @@ impl_Debug! { mod imp { use super::*; impl_Display!( - i8 as u8 named fmt_i8, - u8 named fmt_u8, - i16 as u16 named fmt_i16, - u16 named fmt_u16, - i32 as u32 named fmt_i32, - u32 named fmt_u32, - i64 as u64 named fmt_i64, - u64 named fmt_u64, - isize as usize named fmt_isize, - usize named fmt_usize, + i8, u8, + i16, u16, + i32, u32, + i64, u64, + isize, usize, ; as u64 via to_u64 named fmt_u64 ); impl_Exp!( @@ -545,18 +550,13 @@ mod imp { mod imp { use super::*; impl_Display!( - i8 as u8 named fmt_i8, - u8 named fmt_u8, - i16 as u16 named fmt_i16, - u16 named fmt_u16, - i32 as u32 named fmt_i32, - u32 named fmt_u32, - isize as usize named fmt_isize, - usize named fmt_usize, + i8, u8, + i16, u16, + i32, u32, + isize, usize, ; as u32 via to_u32 named fmt_u32); impl_Display!( - i64 as u64 named fmt_i64, - u64 named fmt_u64, + i64, u64, ; as u64 via to_u64 named fmt_u64); impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32); From 0465f71d600dbf9591b27ac569fa428cd5f7c013 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 21 Nov 2024 01:34:50 +0000 Subject: [PATCH 08/20] Stop being so bail-y in candidate assembly --- .../src/traits/select/candidate_assembly.rs | 28 ------ .../src/traits/select/mod.rs | 4 - compiler/rustc_ty_utils/src/ty.rs | 6 +- tests/crashes/124350.rs | 17 ---- tests/crashes/125758.rs | 26 ------ tests/crashes/127351.rs | 17 ---- tests/crashes/127353.rs | 18 ---- tests/crashes/127742.rs | 11 --- tests/crashes/130521.rs | 2 +- .../generic_const_exprs/bad-multiply.rs | 18 ++++ .../generic_const_exprs/bad-multiply.stderr | 18 ++++ tests/ui/const-generics/kind_mismatch.rs | 1 - tests/ui/const-generics/kind_mismatch.stderr | 24 +----- .../generic-associated-types/issue-71176.rs | 4 +- .../issue-71176.stderr | 19 +++- .../layout/ice-type-error-in-tail-124031.rs | 3 + .../ice-type-error-in-tail-124031.stderr | 16 +++- .../ui/lazy-type-alias/bad-lazy-type-alias.rs | 18 ++++ .../bad-lazy-type-alias.stderr | 28 ++++++ .../region-error-ice-109072.rs | 1 - .../region-error-ice-109072.stderr | 11 +-- .../issue-68830-spurious-diagnostics.rs | 1 - .../issue-68830-spurious-diagnostics.stderr | 14 +-- ...alller-supplied-obligation-issue-121941.rs | 1 + ...er-supplied-obligation-issue-121941.stderr | 16 +++- tests/ui/traits/issue-78372.rs | 1 - tests/ui/traits/issue-78372.stderr | 24 +----- ...onicalize-fresh-infer-vars-issue-103626.rs | 1 + ...alize-fresh-infer-vars-issue-103626.stderr | 25 +++++- tests/ui/traits/span-bug-issue-121414.rs | 3 +- tests/ui/traits/span-bug-issue-121414.stderr | 20 +---- .../bad-tait-no-substs.rs | 21 +++++ .../bad-tait-no-substs.stderr | 86 +++++++++++++++++++ .../bad-transmute-itiat.rs | 22 +++++ .../bad-transmute-itiat.stderr | 10 +++ .../drop-analysis-on-unconstrained-tait.rs} | 5 +- ...drop-analysis-on-unconstrained-tait.stderr | 10 +++ .../wf/wf-in-foreign-fn-decls-issue-80468.rs | 1 - .../wf-in-foreign-fn-decls-issue-80468.stderr | 17 +--- 39 files changed, 328 insertions(+), 240 deletions(-) delete mode 100644 tests/crashes/124350.rs delete mode 100644 tests/crashes/125758.rs delete mode 100644 tests/crashes/127351.rs delete mode 100644 tests/crashes/127353.rs delete mode 100644 tests/crashes/127742.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/bad-multiply.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/bad-multiply.stderr create mode 100644 tests/ui/lazy-type-alias/bad-lazy-type-alias.rs create mode 100644 tests/ui/lazy-type-alias/bad-lazy-type-alias.stderr create mode 100644 tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs create mode 100644 tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr create mode 100644 tests/ui/type-alias-impl-trait/bad-transmute-itiat.rs create mode 100644 tests/ui/type-alias-impl-trait/bad-transmute-itiat.stderr rename tests/{crashes/130956.rs => ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.rs} (88%) create mode 100644 tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.stderr diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 345e1cc31f32b..41d430f06df4a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -91,14 +91,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } else if tcx.is_lang_item(def_id, LangItem::Sized) { // Sized is never implementable by end-users, it is // always automatically computed. - - // FIXME: Consider moving this check to the top level as it - // may also be useful for predicates other than `Sized` - // Error type cannot possibly implement `Sized` (fixes #123154) - if let Err(e) = obligation.predicate.skip_binder().self_ty().error_reported() { - return Err(SelectionError::Overflow(e.into())); - } - let sized_conditions = self.sized_conditions(obligation); self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates); } else if tcx.is_lang_item(def_id, LangItem::Unsize) { @@ -230,13 +222,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result<(), SelectionError<'tcx>> { debug!(?stack.obligation); - // An error type will unify with anything. So, avoid - // matching an error type with `ParamCandidate`. - // This helps us avoid spurious errors like issue #121941. - if stack.obligation.predicate.references_error() { - return Ok(()); - } - let bounds = stack .obligation .param_env @@ -563,19 +548,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { - // Essentially any user-written impl will match with an error type, - // so creating `ImplCandidates` isn't useful. However, we might - // end up finding a candidate elsewhere (e.g. a `BuiltinCandidate` for `Sized`) - // This helps us avoid overflow: see issue #72839 - // Since compilation is already guaranteed to fail, this is just - // to try to show the 'nicest' possible errors to the user. - // We don't check for errors in the `ParamEnv` - in practice, - // it seems to cause us to be overly aggressive in deciding - // to give up searching for candidates, leading to spurious errors. - if obligation.predicate.references_error() { - return; - } - let drcx = DeepRejectCtxt::relate_rigid_infer(self.tcx()); let obligation_args = obligation.predicate.skip_binder().trait_ref.args; self.tcx().for_each_relevant_impl( diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 5b4e895189b0e..e0c862a81f341 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2487,10 +2487,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id); let trait_ref = impl_trait_header.trait_ref.instantiate(self.tcx(), impl_args); - if trait_ref.references_error() { - return Err(()); - } - debug!(?impl_trait_header); let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } = diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 2127ba8a42321..292e777f28802 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -6,8 +6,7 @@ use rustc_index::bit_set::BitSet; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, - TypeVisitor, Upcast, + self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast, }; use rustc_span::DUMMY_SP; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; @@ -95,9 +94,6 @@ fn adt_sized_constraint<'tcx>( let tail_ty = tcx.type_of(tail_def.did).instantiate_identity(); let constraint_ty = sized_constraint_for_ty(tcx, tail_ty)?; - if let Err(guar) = constraint_ty.error_reported() { - return Some(ty::EarlyBinder::bind(Ty::new_error(tcx, guar))); - } // perf hack: if there is a `constraint_ty: Sized` bound, then we know // that the type is sized and do not need to check it on the impl. diff --git a/tests/crashes/124350.rs b/tests/crashes/124350.rs deleted file mode 100644 index d6038f280cf81..0000000000000 --- a/tests/crashes/124350.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ known-bug: #124350 - -struct Node {} - -impl Node -where - SmallVec<{ D * 2 }>:, -{ - fn new() -> Self { - let mut node = Node::new(); - (&a, 0)(); - - node - } -} - -struct SmallVec {} diff --git a/tests/crashes/125758.rs b/tests/crashes/125758.rs deleted file mode 100644 index 86c3b80abab9d..0000000000000 --- a/tests/crashes/125758.rs +++ /dev/null @@ -1,26 +0,0 @@ -//@ known-bug: rust-lang/rust#125758 -#![feature(impl_trait_in_assoc_type)] - -trait Trait: Sized { - type Assoc2; -} - -impl Trait for Bar { - type Assoc2 = impl std::fmt::Debug; -} - -struct Foo { - field: ::Assoc2, -} - -enum Bar { - C = 42, - D = 99, -} - -static BAR: u8 = 42; - -static FOO2: (&Foo, &::Assoc2) = - unsafe { (std::mem::transmute(&BAR), std::mem::transmute(&BAR)) }; - -fn main() {} diff --git a/tests/crashes/127351.rs b/tests/crashes/127351.rs deleted file mode 100644 index e3f415948852d..0000000000000 --- a/tests/crashes/127351.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ known-bug: #127351 -#![feature(lazy_type_alias)] -#![allow(incomplete_features)] - -struct Outer0<'a, T>(ExplicitTypeOutlives<'a, T>); -type ExplicitTypeOutlives<'a, T: 'a> = (&'a (), T); - -pub struct Warns { - _significant_drop: ExplicitTypeOutlives, - field: String, -} - -pub fn test(w: Warns) { - _ = || drop(w.field); -} - -fn main() {} diff --git a/tests/crashes/127353.rs b/tests/crashes/127353.rs deleted file mode 100644 index 9bcb90b5c57f8..0000000000000 --- a/tests/crashes/127353.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ known-bug: #127353 -#![feature(type_alias_impl_trait)] -trait Trait {} -type Alias<'a, U> = impl Trait; - -fn f<'a>() -> Alias<'a, ()> {} - -pub enum UninhabitedVariants { - Tuple(Alias), -} - -struct A; - -fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { - match x {} -} - -fn main() {} diff --git a/tests/crashes/127742.rs b/tests/crashes/127742.rs deleted file mode 100644 index 24add45413566..0000000000000 --- a/tests/crashes/127742.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: #127742 -struct Vtable(dyn Cap); // missing lifetime - -trait Cap<'a> {} - -union Transmute { - t: u64, // ICEs with u64, u128, or usize. Correctly errors with u32. - u: &'static Vtable, -} - -const G: &'static Vtable = unsafe { Transmute { t: 1 }.u }; diff --git a/tests/crashes/130521.rs b/tests/crashes/130521.rs index 7c078ab579094..ccc2b444b822a 100644 --- a/tests/crashes/130521.rs +++ b/tests/crashes/130521.rs @@ -6,7 +6,7 @@ struct Vtable(dyn Cap); trait Cap<'a> {} union Transmute { - t: u64, + t: u128, u: &'static Vtable, } diff --git a/tests/ui/const-generics/generic_const_exprs/bad-multiply.rs b/tests/ui/const-generics/generic_const_exprs/bad-multiply.rs new file mode 100644 index 0000000000000..1af6d5742b1f6 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/bad-multiply.rs @@ -0,0 +1,18 @@ +// regression test for #124350 + +struct Node {} + +impl Node +where + SmallVec<{ D * 2 }>:, + //~^ ERROR generic parameters may not be used in const operations + //~| ERROR constant provided when a type was expected +{ + fn new() -> Self { + Node::new() + } +} + +struct SmallVec(T1); + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/bad-multiply.stderr b/tests/ui/const-generics/generic_const_exprs/bad-multiply.stderr new file mode 100644 index 0000000000000..a8d6cebabe718 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/bad-multiply.stderr @@ -0,0 +1,18 @@ +error: generic parameters may not be used in const operations + --> $DIR/bad-multiply.rs:7:16 + | +LL | SmallVec<{ D * 2 }>:, + | ^ cannot perform const operation using `D` + | + = help: const parameters may only be used as standalone arguments, i.e. `D` + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0747]: constant provided when a type was expected + --> $DIR/bad-multiply.rs:7:14 + | +LL | SmallVec<{ D * 2 }>:, + | ^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/kind_mismatch.rs b/tests/ui/const-generics/kind_mismatch.rs index bab58d5952a5f..ecdc01a5ef901 100644 --- a/tests/ui/const-generics/kind_mismatch.rs +++ b/tests/ui/const-generics/kind_mismatch.rs @@ -20,5 +20,4 @@ pub fn remove_key>() -> S { fn main() { let map: KeyHolder<0> = remove_key::<_, _>(); - //~^ ERROR: the trait bound `KeyHolder<0>: SubsetExcept<_>` is not satisfied } diff --git a/tests/ui/const-generics/kind_mismatch.stderr b/tests/ui/const-generics/kind_mismatch.stderr index e13bc6ee058d0..1487b18961986 100644 --- a/tests/ui/const-generics/kind_mismatch.stderr +++ b/tests/ui/const-generics/kind_mismatch.stderr @@ -14,26 +14,6 @@ LL | impl ContainsKey for KeyHolder {} | | | help: consider changing this type parameter to a const parameter: `const K: u8` -error[E0277]: the trait bound `KeyHolder<0>: SubsetExcept<_>` is not satisfied - --> $DIR/kind_mismatch.rs:22:45 - | -LL | let map: KeyHolder<0> = remove_key::<_, _>(); - | ^ the trait `ContainsKey<0>` is not implemented for `KeyHolder<0>` - | -note: required for `KeyHolder<0>` to implement `SubsetExcept<_>` - --> $DIR/kind_mismatch.rs:15:28 - | -LL | impl> SubsetExcept

for T {} - | -------------- ^^^^^^^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here -note: required by a bound in `remove_key` - --> $DIR/kind_mismatch.rs:17:25 - | -LL | pub fn remove_key>() -> S { - | ^^^^^^^^^^^^^^^ required by this bound in `remove_key` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0747. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/generic-associated-types/issue-71176.rs b/tests/ui/generic-associated-types/issue-71176.rs index b33fda8e15443..7fffe312f4b7b 100644 --- a/tests/ui/generic-associated-types/issue-71176.rs +++ b/tests/ui/generic-associated-types/issue-71176.rs @@ -16,6 +16,8 @@ struct Holder { fn main() { Holder { - inner: Box::new(()), //~ ERROR: the trait `Provider` cannot be made into an object + inner: Box::new(()), + //~^ ERROR: the trait `Provider` cannot be made into an object + //~| ERROR: the trait `Provider` cannot be made into an object }; } diff --git a/tests/ui/generic-associated-types/issue-71176.stderr b/tests/ui/generic-associated-types/issue-71176.stderr index 15d5a3df6f276..1cd2ed0d313dc 100644 --- a/tests/ui/generic-associated-types/issue-71176.stderr +++ b/tests/ui/generic-associated-types/issue-71176.stderr @@ -80,7 +80,24 @@ LL | type A<'a>; = help: consider moving `A` to another trait = help: only type `()` implements the trait, consider using it directly instead -error: aborting due to 5 previous errors +error[E0038]: the trait `Provider` cannot be made into an object + --> $DIR/issue-71176.rs:19:16 + | +LL | inner: Box::new(()), + | ^^^^^^^^^^^^ `Provider` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-71176.rs:2:10 + | +LL | trait Provider { + | -------- this trait cannot be made into an object... +LL | type A<'a>; + | ^ ...because it contains the generic associated type `A` + = help: consider moving `A` to another trait + = help: only type `()` implements the trait, consider using it directly instead + = note: required for the cast from `Box<()>` to `Box<(dyn Provider = _> + 'static), {type error}>` + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0038, E0107. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/layout/ice-type-error-in-tail-124031.rs b/tests/ui/layout/ice-type-error-in-tail-124031.rs index 0a2be11740358..ecd6f3d56f3f4 100644 --- a/tests/ui/layout/ice-type-error-in-tail-124031.rs +++ b/tests/ui/layout/ice-type-error-in-tail-124031.rs @@ -1,3 +1,5 @@ +//@ normalize-stderr-test: "\d+ bits" -> "$$BITS bits" + // Regression test for issue #124031 // Checks that we don't ICE when the tail // of an ADT has a type error @@ -16,5 +18,6 @@ struct Other { fn main() { unsafe { std::mem::transmute::, Option<&Other>>(None); + //~^ ERROR cannot transmute between types of different sizes } } diff --git a/tests/ui/layout/ice-type-error-in-tail-124031.stderr b/tests/ui/layout/ice-type-error-in-tail-124031.stderr index 57dc83f92dfda..a066e8574dc50 100644 --- a/tests/ui/layout/ice-type-error-in-tail-124031.stderr +++ b/tests/ui/layout/ice-type-error-in-tail-124031.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `RefTarget` - --> $DIR/ice-type-error-in-tail-124031.rs:9:1 + --> $DIR/ice-type-error-in-tail-124031.rs:11:1 | LL | type RefTarget; | -------------- `RefTarget` from trait @@ -7,6 +7,16 @@ LL | type RefTarget; LL | impl Trait for () {} | ^^^^^^^^^^^^^^^^^ missing `RefTarget` in implementation -error: aborting due to 1 previous error +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/ice-type-error-in-tail-124031.rs:20:9 + | +LL | std::mem::transmute::, Option<&Other>>(None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `Option<()>` ($BITS bits) + = note: target type: `Option<&Other>` ($BITS bits) + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0046`. +Some errors have detailed explanations: E0046, E0512. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/lazy-type-alias/bad-lazy-type-alias.rs b/tests/ui/lazy-type-alias/bad-lazy-type-alias.rs new file mode 100644 index 0000000000000..6ded9118700c0 --- /dev/null +++ b/tests/ui/lazy-type-alias/bad-lazy-type-alias.rs @@ -0,0 +1,18 @@ +// regression test for #127351 + +#![feature(lazy_type_alias)] +//~^ WARN the feature `lazy_type_alias` is incomplete + +type ExplicitTypeOutlives = T; + +pub struct Warns { + _significant_drop: ExplicitTypeOutlives, + //~^ ERROR missing generics for type alias `ExplicitTypeOutlives` + field: String, +} + +pub fn test(w: Warns) { + let _ = || drop(w.field); +} + +fn main() {} diff --git a/tests/ui/lazy-type-alias/bad-lazy-type-alias.stderr b/tests/ui/lazy-type-alias/bad-lazy-type-alias.stderr new file mode 100644 index 0000000000000..3a5ded60241b1 --- /dev/null +++ b/tests/ui/lazy-type-alias/bad-lazy-type-alias.stderr @@ -0,0 +1,28 @@ +warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/bad-lazy-type-alias.rs:3:12 + | +LL | #![feature(lazy_type_alias)] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #112792 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0107]: missing generics for type alias `ExplicitTypeOutlives` + --> $DIR/bad-lazy-type-alias.rs:9:24 + | +LL | _significant_drop: ExplicitTypeOutlives, + | ^^^^^^^^^^^^^^^^^^^^ expected 1 generic argument + | +note: type alias defined here, with 1 generic parameter: `T` + --> $DIR/bad-lazy-type-alias.rs:6:6 + | +LL | type ExplicitTypeOutlives = T; + | ^^^^^^^^^^^^^^^^^^^^ - +help: add missing generic argument + | +LL | _significant_drop: ExplicitTypeOutlives, + | +++ + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/nll/user-annotations/region-error-ice-109072.rs b/tests/ui/nll/user-annotations/region-error-ice-109072.rs index bcdc6651cf5bb..3f2ad3ccbf582 100644 --- a/tests/ui/nll/user-annotations/region-error-ice-109072.rs +++ b/tests/ui/nll/user-annotations/region-error-ice-109072.rs @@ -11,5 +11,4 @@ impl Lt<'missing> for () { //~ ERROR undeclared lifetime fn main() { let _: <() as Lt<'_>>::T = &(); - //~^ ERROR the trait bound `(): Lt<'_>` is not satisfied } diff --git a/tests/ui/nll/user-annotations/region-error-ice-109072.stderr b/tests/ui/nll/user-annotations/region-error-ice-109072.stderr index c187c17d98c68..d90971bed25ba 100644 --- a/tests/ui/nll/user-annotations/region-error-ice-109072.stderr +++ b/tests/ui/nll/user-annotations/region-error-ice-109072.stderr @@ -21,13 +21,6 @@ help: consider introducing lifetime `'missing` here LL | impl<'missing> Lt<'missing> for () { | ++++++++++ -error[E0277]: the trait bound `(): Lt<'_>` is not satisfied - --> $DIR/region-error-ice-109072.rs:13:13 - | -LL | let _: <() as Lt<'_>>::T = &(); - | ^^ the trait `Lt<'_>` is not implemented for `()` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0261, E0277. -For more information about an error, try `rustc --explain E0261`. +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/specialization/issue-68830-spurious-diagnostics.rs b/tests/ui/specialization/issue-68830-spurious-diagnostics.rs index a7487b8aecb9c..d11ec79833217 100644 --- a/tests/ui/specialization/issue-68830-spurious-diagnostics.rs +++ b/tests/ui/specialization/issue-68830-spurious-diagnostics.rs @@ -17,7 +17,6 @@ impl MyTrait for D { } impl MyTrait for BadStruct { -//~^ ERROR: conflicting implementations of trait `MyTrait<_>` for type `BadStruct` fn foo() {} } diff --git a/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr b/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr index 13f6ae0805dad..0ecec03a023eb 100644 --- a/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr +++ b/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr @@ -4,16 +4,6 @@ error[E0412]: cannot find type `MissingType` in this scope LL | err: MissingType | ^^^^^^^^^^^ not found in this scope -error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `BadStruct` - --> $DIR/issue-68830-spurious-diagnostics.rs:19:1 - | -LL | impl MyTrait for D { - | --------------------------- first implementation here -... -LL | impl MyTrait for BadStruct { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `BadStruct` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0119, E0412. -For more information about an error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.rs b/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.rs index a08407683d8fe..85c70a21f6839 100644 --- a/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.rs +++ b/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.rs @@ -1,5 +1,6 @@ fn function() { foo == 2; //~ ERROR cannot find value `foo` in this scope [E0425] + //~^ ERROR mismatched types } fn main() {} diff --git a/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.stderr b/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.stderr index 2da731dcc4b14..8010c0842ba97 100644 --- a/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.stderr +++ b/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.stderr @@ -4,6 +4,18 @@ error[E0425]: cannot find value `foo` in this scope LL | foo == 2; | ^^^ not found in this scope -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.rs:2:12 + | +LL | fn function() { + | - expected this type parameter +LL | foo == 2; + | ^ expected type parameter `T`, found integer + | + = note: expected type parameter `T` + found type `{integer}` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0425`. +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/issue-78372.rs b/tests/ui/traits/issue-78372.rs index 82b13cc0b6238..f03baf2ceca36 100644 --- a/tests/ui/traits/issue-78372.rs +++ b/tests/ui/traits/issue-78372.rs @@ -10,5 +10,4 @@ trait X { } trait Marker {} impl Marker for dyn Foo {} -//~^ ERROR cannot be made into an object fn main() {} diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr index 4cc2c59fd8dc5..86234d15a5d4b 100644 --- a/tests/ui/traits/issue-78372.stderr +++ b/tests/ui/traits/issue-78372.stderr @@ -55,24 +55,6 @@ LL | impl DispatchFromDyn> for T {} = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/issue-78372.rs:12:17 - | -LL | fn foo(self: Smaht); - | -------------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` -... -LL | impl Marker for dyn Foo {} - | ^^^^^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-78372.rs:9:18 - | -LL | trait Foo: X {} - | --- this trait cannot be made into an object... -LL | trait X { -LL | fn foo(self: Smaht); - | ^^^^^^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on - error[E0307]: invalid `self` parameter type: `Smaht` --> $DIR/issue-78372.rs:9:18 | @@ -88,7 +70,7 @@ error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion LL | impl DispatchFromDyn> for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0038, E0307, E0378, E0412, E0658. -For more information about an error, try `rustc --explain E0038`. +Some errors have detailed explanations: E0307, E0378, E0412, E0658. +For more information about an error, try `rustc --explain E0307`. diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs index 3af299e5b115a..4aadd45c49c1e 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs @@ -10,6 +10,7 @@ fn w<'a, T: 'a, F: Fn(&'a T)>() { let b: &dyn FromResidual = &(); //~^ ERROR: the trait `FromResidual` cannot be made into an object //~| ERROR: the trait `FromResidual` cannot be made into an object + //~| ERROR: the trait `FromResidual` cannot be made into an object } fn main() {} diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr index 960802e2f8f82..c67a8c05379cd 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr @@ -6,6 +6,29 @@ LL | let b: &dyn FromResidual = &(); | = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause +error[E0038]: the trait `FromResidual` cannot be made into an object + --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:32 + | +LL | let b: &dyn FromResidual = &(); + | ^^^ `FromResidual` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:2:8 + | +LL | trait FromResidual::Residual> { + | ------------ this trait cannot be made into an object... +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^ ...because associated function `from_residual` has no `self` parameter + = note: required for the cast from `&()` to `&dyn FromResidual<{type error}>` +help: consider turning `from_residual` into a method by giving it a `&self` argument + | +LL | fn from_residual(&self, residual: R) -> Self; + | ++++++ +help: alternatively, consider constraining `from_residual` so it does not apply to trait objects + | +LL | fn from_residual(residual: R) -> Self where Self: Sized; + | +++++++++++++++++ + error[E0038]: the trait `FromResidual` cannot be made into an object --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:12 | @@ -28,6 +51,6 @@ help: alternatively, consider constraining `from_residual` so it does not apply LL | fn from_residual(residual: R) -> Self where Self: Sized; | +++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/span-bug-issue-121414.rs b/tests/ui/traits/span-bug-issue-121414.rs index ec38d8c2de6a6..2f4ad34f0c858 100644 --- a/tests/ui/traits/span-bug-issue-121414.rs +++ b/tests/ui/traits/span-bug-issue-121414.rs @@ -6,8 +6,7 @@ impl<'a> Bar for Foo<'f> { //~ ERROR undeclared lifetime type Type = u32; } -fn test() //~ ERROR the trait bound `for<'a> Foo<'a>: Bar` is not satisfied - //~| ERROR the trait bound `for<'a> Foo<'a>: Bar` is not satisfied +fn test() where for<'a> as Bar>::Type: Sized, { diff --git a/tests/ui/traits/span-bug-issue-121414.stderr b/tests/ui/traits/span-bug-issue-121414.stderr index e2ef6672cd57a..744806a341506 100644 --- a/tests/ui/traits/span-bug-issue-121414.stderr +++ b/tests/ui/traits/span-bug-issue-121414.stderr @@ -6,22 +6,6 @@ LL | impl<'a> Bar for Foo<'f> { | | | help: consider introducing lifetime `'f` here: `'f,` -error[E0277]: the trait bound `for<'a> Foo<'a>: Bar` is not satisfied - --> $DIR/span-bug-issue-121414.rs:9:1 - | -LL | / fn test() -LL | | -LL | | where -LL | | for<'a> as Bar>::Type: Sized, - | |__________________________________________^ the trait `for<'a> Bar` is not implemented for `Foo<'a>` - -error[E0277]: the trait bound `for<'a> Foo<'a>: Bar` is not satisfied - --> $DIR/span-bug-issue-121414.rs:9:4 - | -LL | fn test() - | ^^^^ the trait `for<'a> Bar` is not implemented for `Foo<'a>` - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0261, E0277. -For more information about an error, try `rustc --explain E0261`. +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs new file mode 100644 index 0000000000000..18cfb1c1f93be --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs @@ -0,0 +1,21 @@ +// regression test for #127353 + +#![feature(type_alias_impl_trait)] +trait Trait {} +type Alias<'a, U> = impl Trait; +//~^ ERROR unconstrained opaque type + +pub enum UninhabitedVariants { + Tuple(Alias), + //~^ ERROR missing lifetime specifier + //~| ERROR missing generics + //~| ERROR non-defining opaque type use in defining scope +} + +fn uwu(x: UninhabitedVariants) { + //~^ ERROR item does not constrain + match x {} + //~^ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr new file mode 100644 index 0000000000000..cf366c55ea816 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr @@ -0,0 +1,86 @@ +error[E0106]: missing lifetime specifier + --> $DIR/bad-tait-no-substs.rs:9:11 + | +LL | Tuple(Alias), + | ^^^^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ pub enum UninhabitedVariants<'a> { +LL ~ Tuple(Alias<'a>), + | + +error[E0107]: missing generics for type alias `Alias` + --> $DIR/bad-tait-no-substs.rs:9:11 + | +LL | Tuple(Alias), + | ^^^^^ expected 1 generic argument + | +note: type alias defined here, with 1 generic parameter: `U` + --> $DIR/bad-tait-no-substs.rs:5:6 + | +LL | type Alias<'a, U> = impl Trait; + | ^^^^^ - +help: add missing generic argument + | +LL | Tuple(Alias), + | +++ + +error[E0792]: non-defining opaque type use in defining scope + --> $DIR/bad-tait-no-substs.rs:9:11 + | +LL | Tuple(Alias), + | ^^^^^ argument `'_` is not a generic parameter + | +note: for this opaque type + --> $DIR/bad-tait-no-substs.rs:5:21 + | +LL | type Alias<'a, U> = impl Trait; + | ^^^^^^^^^^^^^ + +error: item does not constrain `Alias::{opaque#0}`, but has it in its signature + --> $DIR/bad-tait-no-substs.rs:15:4 + | +LL | fn uwu(x: UninhabitedVariants) { + | ^^^ + | + = note: consider moving the opaque type's declaration and defining uses into a separate module +note: this opaque type is in the signature + --> $DIR/bad-tait-no-substs.rs:5:21 + | +LL | type Alias<'a, U> = impl Trait; + | ^^^^^^^^^^^^^ + +error: unconstrained opaque type + --> $DIR/bad-tait-no-substs.rs:5:21 + | +LL | type Alias<'a, U> = impl Trait; + | ^^^^^^^^^^^^^ + | + = note: `Alias` must be used in combination with a concrete type within the same module + +error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` not covered + --> $DIR/bad-tait-no-substs.rs:17:11 + | +LL | match x {} + | ^ pattern `UninhabitedVariants::Tuple(_)` not covered + | +note: `UninhabitedVariants` defined here + --> $DIR/bad-tait-no-substs.rs:8:10 + | +LL | pub enum UninhabitedVariants { + | ^^^^^^^^^^^^^^^^^^^ +LL | Tuple(Alias), + | ----- not covered + = note: the matched value is of type `UninhabitedVariants` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ match x { +LL + UninhabitedVariants::Tuple(_) => todo!(), +LL + } + | + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0004, E0106, E0107, E0792. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/type-alias-impl-trait/bad-transmute-itiat.rs b/tests/ui/type-alias-impl-trait/bad-transmute-itiat.rs new file mode 100644 index 0000000000000..8314b28eeac4b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bad-transmute-itiat.rs @@ -0,0 +1,22 @@ +// regression test for rust-lang/rust#125758 + +#![feature(impl_trait_in_assoc_type)] + +trait Trait { + type Assoc2; +} + +struct Bar; +impl Trait for Bar { + type Assoc2 = impl std::fmt::Debug; + //~^ ERROR unconstrained opaque type +} + +struct Foo { + field: ::Assoc2, +} + +static BAR: u8 = 42; +static FOO2: &Foo = unsafe { std::mem::transmute(&BAR) }; + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/bad-transmute-itiat.stderr b/tests/ui/type-alias-impl-trait/bad-transmute-itiat.stderr new file mode 100644 index 0000000000000..6cbf6c83ff4ce --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bad-transmute-itiat.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/bad-transmute-itiat.rs:11:19 + | +LL | type Assoc2 = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `Assoc2` must be used in combination with a concrete type within the same impl + +error: aborting due to 1 previous error + diff --git a/tests/crashes/130956.rs b/tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.rs similarity index 88% rename from tests/crashes/130956.rs rename to tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.rs index ebb986d123f91..4332f1264a80b 100644 --- a/tests/crashes/130956.rs +++ b/tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.rs @@ -1,8 +1,11 @@ -//@ known-bug: #130956 +// Regression test for #130956 + +#![feature(type_alias_impl_trait)] mod impl_trait_mod { use super::*; pub type OpaqueBlock = impl Trait; + //~^ ERROR unconstrained opaque type pub type OpaqueIf = impl Trait; pub struct BlockWrapper(OpaqueBlock); diff --git a/tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.stderr b/tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.stderr new file mode 100644 index 0000000000000..8e5838d5ddf55 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/drop-analysis-on-unconstrained-tait.rs:7:28 + | +LL | pub type OpaqueBlock = impl Trait; + | ^^^^^^^^^^ + | + = note: `OpaqueBlock` must be used in combination with a concrete type within the same module + +error: aborting due to 1 previous error + diff --git a/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs index e6d4e2ee01a27..0be5127dcc4da 100644 --- a/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs +++ b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs @@ -14,5 +14,4 @@ impl Trait for Ref {} //~ ERROR: implicit elided lifetime not allowed here extern "C" { pub fn repro(_: Wrapper); - //~^ ERROR the trait bound `Ref<'_>: Trait` is not satisfied } diff --git a/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr index 59b55b2732d30..0af4ab022e1eb 100644 --- a/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr +++ b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr @@ -9,19 +9,6 @@ help: indicate the anonymous lifetime LL | impl Trait for Ref<'_> {} | ++++ -error[E0277]: the trait bound `Ref<'_>: Trait` is not satisfied - --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:21 - | -LL | pub fn repro(_: Wrapper); - | ^^^^^^^^^^^^ the trait `Trait` is not implemented for `Ref<'_>` - | -note: required by a bound in `Wrapper` - --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:8:23 - | -LL | pub struct Wrapper(T); - | ^^^^^ required by this bound in `Wrapper` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0726. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0726`. From 5d30436d244d207406ec8e4a2fbeb510555cba20 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 21 Nov 2024 18:40:36 +0800 Subject: [PATCH 09/20] Re-delay a resolve `bug` For the code pattern reported in , ```rs impl Foo { fn fun() { let S { ref Self } = todo!(); } } ``` converted this to a `span_bug` from a `span_delayed_bug` because this specific self-ctor code pattern lacked test coverage. It turns out this can be hit but we just lacked test coverage, so change it back to a `span_delayed_bug` and add a target tested case. --- compiler/rustc_resolve/src/late.rs | 6 +++--- tests/ui/pattern/self-ctor-133272.rs | 21 +++++++++++++++++++++ tests/ui/pattern/self-ctor-133272.stderr | 15 +++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 tests/ui/pattern/self-ctor-133272.rs create mode 100644 tests/ui/pattern/self-ctor-133272.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 26b345f5941c4..02cb9da6e9ab2 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3940,12 +3940,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } Res::SelfCtor(_) => { // We resolve `Self` in pattern position as an ident sometimes during recovery, - // so delay a bug instead of ICEing. (Note: is this no longer true? We now ICE. If - // this triggers, please convert to a delayed bug and add a test.) - self.r.dcx().span_bug( + // so delay a bug instead of ICEing. + self.r.dcx().span_delayed_bug( ident.span, "unexpected `SelfCtor` in pattern, expected identifier" ); + None } _ => span_bug!( ident.span, diff --git a/tests/ui/pattern/self-ctor-133272.rs b/tests/ui/pattern/self-ctor-133272.rs new file mode 100644 index 0000000000000..ad64d6b88cd91 --- /dev/null +++ b/tests/ui/pattern/self-ctor-133272.rs @@ -0,0 +1,21 @@ +//! Regression test for , where a `ref Self` ctor +//! makes it possible to hit a `delayed_bug` that was converted into a `span_bug` in +//! , and hitting this reveals that we did not have +//! test coverage for this specific code pattern (heh) previously. +//! +//! # References +//! +//! - ICE bug report: . +//! - Previous PR to change `delayed_bug` -> `span_bug`: +//! +#![crate_type = "lib"] + +struct Foo; + +impl Foo { + fn fun() { + let S { ref Self } = todo!(); + //~^ ERROR expected identifier, found keyword `Self` + //~| ERROR cannot find struct, variant or union type `S` in this scope + } +} diff --git a/tests/ui/pattern/self-ctor-133272.stderr b/tests/ui/pattern/self-ctor-133272.stderr new file mode 100644 index 0000000000000..bca55a43d9c08 --- /dev/null +++ b/tests/ui/pattern/self-ctor-133272.stderr @@ -0,0 +1,15 @@ +error: expected identifier, found keyword `Self` + --> $DIR/self-ctor-133272.rs:17:21 + | +LL | let S { ref Self } = todo!(); + | ^^^^ expected identifier, found keyword + +error[E0422]: cannot find struct, variant or union type `S` in this scope + --> $DIR/self-ctor-133272.rs:17:13 + | +LL | let S { ref Self } = todo!(); + | ^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0422`. From 9a30362f170278357fc1fa7ef3f054d6dde397f1 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 17 Oct 2024 17:08:31 -0600 Subject: [PATCH 10/20] Update TRPL to latest, including new Chapter 17: Async and Await This also incorporates a number of other changes and fixes which would normally have been part of the automatic update, but which were blocked from landing because of the changes required to support shipping a crate as part of the chapter, along with those changes. --- src/doc/book | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/book b/src/doc/book index f38ce8baef98c..e16dd73690a6c 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit f38ce8baef98cb20229e56f1be2d50e345f11792 +Subproject commit e16dd73690a6cc3ecdc5f5d94bbc3ce158a42e16 From 34b4518b5c9d30e3d8f6c068d821a7b9eb737626 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 17 Oct 2024 16:08:36 -0600 Subject: [PATCH 11/20] Update messages which reference book chs. 17-20 With the insertion of a new chapter 17 on async and await to _The Rust Programming Language_, references in compiler output to later chapters need to be updated to avoid confusing users. Redirects exist so that users who click old links will end up in the right place anyway, but this way users will be directed to the right URL in the first place. --- compiler/rustc_mir_build/messages.ftl | 2 +- compiler/rustc_parse/messages.ftl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 55149570dbc4d..673a9bceb2718 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -203,7 +203,7 @@ mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper = mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper -mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html mir_build_moved = value is moved into `{$name}` here diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index cafd4b6dca28f..8c4f669c332b2 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -827,7 +827,7 @@ parse_unexpected_expr_in_pat = }, found an expression .label = not a pattern - .note = arbitrary expressions are not allowed in patterns: + .note = arbitrary expressions are not allowed in patterns: parse_unexpected_expr_in_pat_const_sugg = consider extracting the expression into a `const` From 85c582cdbea6164073c620a6f52b457c25a2653f Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 18 Oct 2024 12:49:00 -0600 Subject: [PATCH 12/20] Add support for `--library-path` to `rustbook test` This makes it possible to test an mdbook which has dependencies other than the direct crate for the book itself, e.g. the `trpl` crate used in _The Rust Programming Language_. --- src/tools/rustbook/src/main.rs | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index f905b9277ff51..dc89362538b6f 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -31,6 +31,20 @@ fn main() { (Defaults to the current directory when omitted)") .value_parser(clap::value_parser!(PathBuf)); + // Note: we don't parse this into a `PathBuf` because it is comma separated + // strings *and* we will ultimately pass it into `MDBook::test()`, which + // accepts `Vec<&str>`. Although it is a bit annoying that `-l/--lang` and + // `-L/--library-path` are so close, this is the same set of arguments we + // would pass when invoking mdbook on the CLI, so making them match when + // invoking rustbook makes for good consistency. + let library_path_arg = arg!( + -L --"library-path" + "A comma-separated list of directories to add to the crate search\n\ + path when building tests" + ) + .required(false) + .value_parser(parse_library_paths); + let matches = Command::new("rustbook") .about("Build a book with mdBook") .author("Steve Klabnik ") @@ -48,7 +62,8 @@ fn main() { .subcommand( Command::new("test") .about("Tests that a book's Rust code samples compile") - .arg(dir_arg), + .arg(dir_arg) + .arg(library_path_arg), ) .get_matches(); @@ -113,8 +128,12 @@ pub fn build(args: &ArgMatches) -> Result3<()> { fn test(args: &ArgMatches) -> Result3<()> { let book_dir = get_book_dir(args); + let library_paths = args + .try_get_one::>("library-path")? + .map(|v| v.iter().map(|s| s.as_str()).collect::>()) + .unwrap_or_default(); let mut book = load_book(&book_dir)?; - book.test(vec![]) + book.test(library_paths) } fn get_book_dir(args: &ArgMatches) -> PathBuf { @@ -132,6 +151,10 @@ fn load_book(book_dir: &Path) -> Result3 { Ok(book) } +fn parse_library_paths(input: &str) -> Result, String> { + Ok(input.split(",").map(String::from).collect()) +} + fn handle_error(error: mdbook::errors::Error) -> ! { eprintln!("Error: {}", error); @@ -139,5 +162,5 @@ fn handle_error(error: mdbook::errors::Error) -> ! { eprintln!("\tCaused By: {}", cause); } - ::std::process::exit(101); + std::process::exit(101); } From e0d7cf07ee8822693a5dc3cf999bd814e77411b0 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 18 Oct 2024 12:49:00 -0600 Subject: [PATCH 13/20] Update bootstrap tests to support book dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since TRPL now depends on a `trpl` crate, the test needs to be able to build that crate to run mdbook against it, and also to invoke mdbook with `--library-path` in that case. Use the support for that flag added to `rustbook` in the previous change to invoke it with the path to the dependencies it will need to run `rustdoc` tests which reference `trpl`. Co-authored-by: Onur Özkan --- src/bootstrap/src/core/build_steps/test.rs | 67 +++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 532c8f767eb10..dcf7f4a7cc10c 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -3,12 +3,14 @@ //! `./x.py test` (aka [`Kind::Test`]) is currently allowed to reach build steps in other modules. //! However, this contains ~all test parts we expect people to be able to build and run locally. +use std::collections::HashSet; use std::ffi::{OsStr, OsString}; use std::path::{Path, PathBuf}; use std::{env, fs, iter}; use clap_complete::shells; +use crate::core::build_steps::compile::run_cargo; use crate::core::build_steps::doc::DocumentationFormat; use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget; use crate::core::build_steps::tool::{self, SourceType, Tool}; @@ -2185,6 +2187,7 @@ struct BookTest { path: PathBuf, name: &'static str, is_ext_doc: bool, + dependencies: Vec<&'static str>, } impl Step for BookTest { @@ -2237,6 +2240,57 @@ impl BookTest { // Books often have feature-gated example text. rustbook_cmd.env("RUSTC_BOOTSTRAP", "1"); rustbook_cmd.env("PATH", new_path).arg("test").arg(path); + + // Books may also need to build dependencies. For example, `TheBook` has + // code samples which use the `trpl` crate. For the `rustdoc` invocation + // to find them them successfully, they need to be built first and their + // paths used to generate the + let libs = if !self.dependencies.is_empty() { + let mut lib_paths = vec![]; + for dep in self.dependencies { + let mode = Mode::ToolRustc; + let target = builder.config.build; + let cargo = tool::prepare_tool_cargo( + builder, + compiler, + mode, + target, + Kind::Build, + dep, + SourceType::Submodule, + &[], + ); + + let stamp = builder + .cargo_out(compiler, mode, target) + .join(PathBuf::from(dep).file_name().unwrap()) + .with_extension("stamp"); + + let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false); + let directories = output_paths + .into_iter() + .filter_map(|p| p.parent().map(ToOwned::to_owned)) + .fold(HashSet::new(), |mut set, dir| { + set.insert(dir); + set + }); + + lib_paths.extend(directories); + } + lib_paths + } else { + vec![] + }; + + if !libs.is_empty() { + let paths = libs + .into_iter() + .map(|path| path.into_os_string()) + .collect::>() + .join(OsStr::new(",")); + rustbook_cmd.args([OsString::from("--library-path"), paths]); + } + builder.add_rust_test_threads(&mut rustbook_cmd); let _guard = builder.msg( Kind::Test, @@ -2295,6 +2349,7 @@ macro_rules! test_book { $name:ident, $path:expr, $book_name:expr, default=$default:expr $(,submodules = $submodules:expr)? + $(,dependencies=$dependencies:expr)? ; )+) => { $( @@ -2324,11 +2379,21 @@ macro_rules! test_book { builder.require_submodule(submodule, None); } )* + + let dependencies = vec![]; + $( + let mut dependencies = dependencies; + for dep in $dependencies { + dependencies.push(dep); + } + )? + builder.ensure(BookTest { compiler: self.compiler, path: PathBuf::from($path), name: $book_name, is_ext_doc: !$default, + dependencies, }); } } @@ -2343,7 +2408,7 @@ test_book!( RustcBook, "src/doc/rustc", "rustc", default=true; RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"]; EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"]; - TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"]; + TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"]; UnstableBook, "src/doc/unstable-book", "unstable-book", default=true; EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"]; ); From 99832cb3615a00521467bf01f75d85a55d631347 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 18 Oct 2024 12:49:00 -0600 Subject: [PATCH 14/20] rustbook: fix two small typos --- src/tools/rustbook/Cargo.toml | 2 +- src/tools/rustbook/src/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 2c29a2848b7e5..854c454733759 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -12,7 +12,7 @@ env_logger = "0.11" mdbook-trpl-listing = { path = "../../doc/book/packages/mdbook-trpl-listing" } mdbook-trpl-note = { path = "../../doc/book/packages/mdbook-trpl-note" } mdbook-i18n-helpers = "0.3.3" -mdbook-spec = { path = "../../doc/reference/mdbook-spec"} +mdbook-spec = { path = "../../doc/reference/mdbook-spec" } [dependencies.mdbook] version = "0.4.37" diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index dc89362538b6f..a1ef18610b000 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -67,7 +67,7 @@ fn main() { ) .get_matches(); - // Check which subcomamnd the user ran... + // Check which subcommand the user ran... match matches.subcommand() { Some(("build", sub_matches)) => { if let Err(e) = build(sub_matches) { From 21dd59f361a2f1804bc78ea9cd2b77d3afd838ba Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 30 Oct 2024 13:08:08 -0600 Subject: [PATCH 15/20] Update tests for new TRPL chapter order --- compiler/rustc_hir_typeck/src/lib.rs | 2 +- .../rustc_resolve/src/late/diagnostics.rs | 2 +- .../2229_closure_analysis/bad-pattern.stderr | 14 ++-- .../ui/consts/const-match-check.eval1.stderr | 2 +- .../ui/consts/const-match-check.eval2.stderr | 2 +- .../consts/const-match-check.matchck.stderr | 8 +-- .../consts/const-pattern-irrefutable.stderr | 8 +-- .../non-exhaustive-destructure.stderr | 2 +- tests/ui/empty/empty-never-array.stderr | 2 +- tests/ui/error-codes/E0005.stderr | 2 +- .../feature-gate-exhaustive-patterns.stderr | 2 +- ...-half-open-range-patterns-in-slices.stderr | 2 +- ...pats-inclusive-dotdotdot-bad-syntax.stderr | 2 +- ...lf-open-range-pats-inclusive-no-end.stderr | 4 +- .../range_pat_interactions1.stderr | 2 +- .../range_pat_interactions2.stderr | 2 +- .../slice_pattern_syntax_problem1.stderr | 2 +- tests/ui/issues/issue-55587.stderr | 2 +- ...tialized-refutable-let-issue-123844.stderr | 2 +- .../loops/loop-else-break-with-value.stderr | 2 +- tests/ui/match/match-fn-call.stderr | 4 +- tests/ui/mir/issue-112269.stderr | 4 +- .../ui/never_type/exhaustive_patterns.stderr | 2 +- ...een-expanded-earlier-non-exhaustive.stderr | 2 +- tests/ui/parser/bad-name.stderr | 2 +- tests/ui/parser/issues/issue-24197.stderr | 2 +- tests/ui/parser/issues/issue-24375.stderr | 2 +- tests/ui/parser/pat-lt-bracket-5.stderr | 2 +- tests/ui/parser/pat-lt-bracket-6.stderr | 2 +- tests/ui/parser/pat-ranges-3.stderr | 4 +- .../parser/recover/recover-pat-exprs.stderr | 66 +++++++++---------- .../parser/recover/recover-pat-issues.stderr | 12 ++-- .../ui/parser/recover/recover-pat-lets.stderr | 10 +-- .../parser/recover/recover-pat-ranges.stderr | 12 ++-- .../recover/recover-pat-wildcards.stderr | 2 +- .../parser/recover/recover-range-pats.stderr | 18 ++--- tests/ui/pattern/fn-in-pat.stderr | 2 +- tests/ui/pattern/issue-106552.stderr | 4 +- .../pattern-binding-disambiguation.stderr | 2 +- ...tch-check-notes.exhaustive_patterns.stderr | 2 +- .../empty-match-check-notes.normal.stderr | 2 +- .../empty-types.exhaustive_patterns.stderr | 2 +- .../empty-types.min_exh_pats.stderr | 4 +- .../usefulness/empty-types.never_pats.stderr | 6 +- .../usefulness/empty-types.normal.stderr | 6 +- .../ui/pattern/usefulness/issue-31561.stderr | 2 +- .../usefulness/non-exhaustive-defined-here.rs | 8 +-- .../non-exhaustive-defined-here.stderr | 8 +-- .../refutable-pattern-errors.stderr | 2 +- ...recursive-types-are-not-uninhabited.stderr | 2 +- tests/ui/resolve/issue-10200.stderr | 2 +- .../omitted-patterns.stderr | 2 +- ...s-in-pattern-with-ty-err-doesnt-ice.stderr | 2 +- ...const-pat-non-exaustive-let-new-var.stderr | 2 +- ...ted-irrefutable.exhaustive_patterns.stderr | 2 +- ...irrefutable.min_exhaustive_patterns.stderr | 2 +- .../uninhabited-irrefutable.normal.stderr | 2 +- 57 files changed, 139 insertions(+), 139 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 63dccf8b0ce04..91ea34eb54d35 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -364,7 +364,7 @@ fn report_unexpected_variant_res( .with_code(err_code); match res { Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == E0164 => { - let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html"; + let patterns_url = "https://doc.rust-lang.org/book/ch19-00-patterns.html"; err.with_span_label(span, "`fn` calls are not allowed in patterns") .with_help(format!("for more information, visit {patterns_url}")) } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 09f5a8e96d3de..4a1570499648f 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1206,7 +1206,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let PathSource::TupleStruct(_, _) = source else { return }; let Some(Res::Def(DefKind::Fn, _)) = res else { return }; err.primary_message("expected a pattern, found a function call"); - err.note("function calls are not allowed in patterns: "); + err.note("function calls are not allowed in patterns: "); } fn suggest_changing_type_to_const_param( diff --git a/tests/ui/closures/2229_closure_analysis/bad-pattern.stderr b/tests/ui/closures/2229_closure_analysis/bad-pattern.stderr index 5f980c46a1f54..b5ad8eb790f2b 100644 --- a/tests/ui/closures/2229_closure_analysis/bad-pattern.stderr +++ b/tests/ui/closures/2229_closure_analysis/bad-pattern.stderr @@ -5,7 +5,7 @@ LL | let 0 = v1; | ^ pattern `1_u32..=u32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `u32` help: you might want to use `if let` to ignore the variant that isn't matched | @@ -23,7 +23,7 @@ LL | let (0 | 1) = v1; | ^^^^^ pattern `2_u32..=u32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `u32` help: you might want to use `if let` to ignore the variant that isn't matched | @@ -37,7 +37,7 @@ LL | let 1.. = v1; | ^^^ pattern `0_u32` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `u32` help: you might want to use `if let` to ignore the variant that isn't matched | @@ -51,7 +51,7 @@ LL | let [0, 0, 0, 0] = v2; | ^^^^^^^^^^^^ pattern `[1_u32..=u32::MAX, _, _, _]` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `[u32; 4]` help: you might want to use `if let` to ignore the variant that isn't matched | @@ -65,7 +65,7 @@ LL | let [0] = v4; | ^^^ patterns `&[]` and `&[_, _, ..]` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `&[u32]` help: you might want to use `if let` to ignore the variants that aren't matched | @@ -79,7 +79,7 @@ LL | let Refutable::A = v3; | ^^^^^^^^^^^^ pattern `Refutable::B` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html note: `Refutable` defined here --> $DIR/bad-pattern.rs:4:6 | @@ -104,7 +104,7 @@ LL | let PAT = v1; | ^^^ pattern `1_u32..=u32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `u32` help: introduce a variable instead | diff --git a/tests/ui/consts/const-match-check.eval1.stderr b/tests/ui/consts/const-match-check.eval1.stderr index 84890214861b8..b1827009d2adc 100644 --- a/tests/ui/consts/const-match-check.eval1.stderr +++ b/tests/ui/consts/const-match-check.eval1.stderr @@ -5,7 +5,7 @@ LL | A = { let 0 = 0; 0 }, | ^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | diff --git a/tests/ui/consts/const-match-check.eval2.stderr b/tests/ui/consts/const-match-check.eval2.stderr index 0aa12eb86dddc..04ac58bfe402f 100644 --- a/tests/ui/consts/const-match-check.eval2.stderr +++ b/tests/ui/consts/const-match-check.eval2.stderr @@ -5,7 +5,7 @@ LL | let x: [i32; { let 0 = 0; 0 }] = []; | ^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | diff --git a/tests/ui/consts/const-match-check.matchck.stderr b/tests/ui/consts/const-match-check.matchck.stderr index bcca4c2a64783..05ddc4c821955 100644 --- a/tests/ui/consts/const-match-check.matchck.stderr +++ b/tests/ui/consts/const-match-check.matchck.stderr @@ -5,7 +5,7 @@ LL | const X: i32 = { let 0 = 0; 0 }; | ^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | @@ -23,7 +23,7 @@ LL | static Y: i32 = { let 0 = 0; 0 }; | ^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | @@ -41,7 +41,7 @@ LL | const X: i32 = { let 0 = 0; 0 }; | ^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | @@ -59,7 +59,7 @@ LL | const X: i32 = { let 0 = 0; 0 }; | ^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | diff --git a/tests/ui/consts/const-pattern-irrefutable.stderr b/tests/ui/consts/const-pattern-irrefutable.stderr index afb67a3a118a4..646426c942689 100644 --- a/tests/ui/consts/const-pattern-irrefutable.stderr +++ b/tests/ui/consts/const-pattern-irrefutable.stderr @@ -8,7 +8,7 @@ LL | let a = 4; | ^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `u8` help: introduce a variable instead | @@ -25,7 +25,7 @@ LL | let c = 4; | ^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `u8` help: introduce a variable instead | @@ -42,7 +42,7 @@ LL | let d = (4, 4); | ^ patterns `(0_u8..=1_u8, _)` and `(3_u8..=u8::MAX, _)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `(u8, u8)` help: introduce a variable instead | @@ -59,7 +59,7 @@ LL | let e = S { | ^ pattern `S { foo: 1_u8..=u8::MAX }` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html note: `S` defined here --> $DIR/const-pattern-irrefutable.rs:15:8 | diff --git a/tests/ui/destructuring-assignment/non-exhaustive-destructure.stderr b/tests/ui/destructuring-assignment/non-exhaustive-destructure.stderr index b9ceaa4af7ba0..88f7d2da47c28 100644 --- a/tests/ui/destructuring-assignment/non-exhaustive-destructure.stderr +++ b/tests/ui/destructuring-assignment/non-exhaustive-destructure.stderr @@ -5,7 +5,7 @@ LL | None = Some(3); | ^^^^ pattern `Some(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `Option` help: you might want to use `if let` to ignore the variant that isn't matched | diff --git a/tests/ui/empty/empty-never-array.stderr b/tests/ui/empty/empty-never-array.stderr index 0104a43553843..f9f39a6371e26 100644 --- a/tests/ui/empty/empty-never-array.stderr +++ b/tests/ui/empty/empty-never-array.stderr @@ -5,7 +5,7 @@ LL | let Helper::U(u) = Helper::T(t, []); | ^^^^^^^^^^^^ pattern `Helper::T(_, _)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html note: `Helper` defined here --> $DIR/empty-never-array.rs:3:6 | diff --git a/tests/ui/error-codes/E0005.stderr b/tests/ui/error-codes/E0005.stderr index 4be37e2e45497..c643ee07a3739 100644 --- a/tests/ui/error-codes/E0005.stderr +++ b/tests/ui/error-codes/E0005.stderr @@ -5,7 +5,7 @@ LL | let Some(y) = x; | ^^^^^^^ pattern `None` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `Option` help: you might want to use `let else` to handle the variant that isn't matched | diff --git a/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr index 4836ffe172318..b596da8463f21 100644 --- a/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr +++ b/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr @@ -5,7 +5,7 @@ LL | let Ok(_x) = &foo(); | ^^^^^^ pattern `&Err(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `&Result` help: you might want to use `let else` to handle the variant that isn't matched | diff --git a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr index af11bc82d0c2e..65903dbe12e57 100644 --- a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr +++ b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr @@ -15,7 +15,7 @@ LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `[i32::MIN..=2_i32, ..]` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `[i32; 8]` help: you might want to use `let else` to handle the variant that isn't matched | diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr index 0f60cd397b997..aa3d2cd2d904f 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr @@ -67,7 +67,7 @@ LL | mac!(0); | ------- in this macro invocation | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr index 204ee373bc538..63258f3538313 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr @@ -94,7 +94,7 @@ LL | mac!(0); | ------- in this macro invocation | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -108,7 +108,7 @@ LL | mac!(0); | ------- in this macro invocation | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr index e2916725fbd90..62be2ef7a4d83 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr +++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr @@ -4,7 +4,7 @@ error: expected a pattern range bound, found an expression LL | 0..5+1 => errors_only.push(x), | ^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 5+1; diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr index f54e07c3a6370..dbe7f4482eed4 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr +++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr @@ -16,7 +16,7 @@ error: expected a pattern range bound, found an expression LL | 0..=(5+1) => errors_only.push(x), | ^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 5+1; diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr index 4951591990462..17b65c1dae548 100644 --- a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr +++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr @@ -15,7 +15,7 @@ LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `[i32::MIN..=2_i32, ..]` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `[i32; 8]` help: you might want to use `let else` to handle the variant that isn't matched | diff --git a/tests/ui/issues/issue-55587.stderr b/tests/ui/issues/issue-55587.stderr index eec6426a29950..7a5d0e281007f 100644 --- a/tests/ui/issues/issue-55587.stderr +++ b/tests/ui/issues/issue-55587.stderr @@ -4,7 +4,7 @@ error[E0164]: expected tuple struct or tuple variant, found associated function LL | let Path::new(); | ^^^^^^^^^^^ `fn` calls are not allowed in patterns | - = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html + = help: for more information, visit https://doc.rust-lang.org/book/ch19-00-patterns.html error: aborting due to 1 previous error diff --git a/tests/ui/let-else/uninitialized-refutable-let-issue-123844.stderr b/tests/ui/let-else/uninitialized-refutable-let-issue-123844.stderr index 13312306c07b7..58f9e267db372 100644 --- a/tests/ui/let-else/uninitialized-refutable-let-issue-123844.stderr +++ b/tests/ui/let-else/uninitialized-refutable-let-issue-123844.stderr @@ -5,7 +5,7 @@ LL | let Some(x); | ^^^^^^^ pattern `None` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `Option` error: aborting due to 1 previous error diff --git a/tests/ui/loops/loop-else-break-with-value.stderr b/tests/ui/loops/loop-else-break-with-value.stderr index ca18f0fdd7f32..da3276c8cd358 100644 --- a/tests/ui/loops/loop-else-break-with-value.stderr +++ b/tests/ui/loops/loop-else-break-with-value.stderr @@ -21,7 +21,7 @@ LL | let Some(1) = loop { | ^^^^^^^ pattern `None` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `Option` help: you might want to use `if let` to ignore the variant that isn't matched | diff --git a/tests/ui/match/match-fn-call.stderr b/tests/ui/match/match-fn-call.stderr index 297aa4cd95def..a3d61947080c0 100644 --- a/tests/ui/match/match-fn-call.stderr +++ b/tests/ui/match/match-fn-call.stderr @@ -4,7 +4,7 @@ error[E0164]: expected tuple struct or tuple variant, found associated function LL | Path::new("foo") => println!("foo"), | ^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns | - = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html + = help: for more information, visit https://doc.rust-lang.org/book/ch19-00-patterns.html error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new` --> $DIR/match-fn-call.rs:8:9 @@ -12,7 +12,7 @@ error[E0164]: expected tuple struct or tuple variant, found associated function LL | Path::new("bar") => println!("bar"), | ^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns | - = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html + = help: for more information, visit https://doc.rust-lang.org/book/ch19-00-patterns.html error: aborting due to 2 previous errors diff --git a/tests/ui/mir/issue-112269.stderr b/tests/ui/mir/issue-112269.stderr index adb662c98a7e8..80f329e2ce026 100644 --- a/tests/ui/mir/issue-112269.stderr +++ b/tests/ui/mir/issue-112269.stderr @@ -7,7 +7,7 @@ LL | let x: i32 = 3; | ^ patterns `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` help: introduce a variable instead | @@ -23,7 +23,7 @@ LL | let y = 4; | ^ patterns `i32::MIN..=2_i32` and `4_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` help: introduce a variable instead | diff --git a/tests/ui/never_type/exhaustive_patterns.stderr b/tests/ui/never_type/exhaustive_patterns.stderr index 1314cbc52f881..1f22b9e619867 100644 --- a/tests/ui/never_type/exhaustive_patterns.stderr +++ b/tests/ui/never_type/exhaustive_patterns.stderr @@ -5,7 +5,7 @@ LL | let Either::A(()) = foo(); | ^^^^^^^^^^^^^ pattern `Either::B(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html note: `Either<(), !>` defined here --> $DIR/exhaustive_patterns.rs:9:6 | diff --git a/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr index fdb1a9bb4b78e..7044b8e035ad8 100644 --- a/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr +++ b/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr @@ -5,7 +5,7 @@ LL | let (0 | (1 | 2)) = 0; | ^^^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | diff --git a/tests/ui/parser/bad-name.stderr b/tests/ui/parser/bad-name.stderr index 5ca248380ee5b..a336923f4fd89 100644 --- a/tests/ui/parser/bad-name.stderr +++ b/tests/ui/parser/bad-name.stderr @@ -10,7 +10,7 @@ error: expected a pattern, found an expression LL | let x.y::.z foo; | ^^^^^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: error: expected one of `(`, `.`, `::`, `:`, `;`, `=`, `?`, `|`, or an operator, found `foo` --> $DIR/bad-name.rs:2:22 diff --git a/tests/ui/parser/issues/issue-24197.stderr b/tests/ui/parser/issues/issue-24197.stderr index c92e165b23b65..4eadc897d88c8 100644 --- a/tests/ui/parser/issues/issue-24197.stderr +++ b/tests/ui/parser/issues/issue-24197.stderr @@ -4,7 +4,7 @@ error: expected a pattern, found an expression LL | let buf[0] = 0; | ^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-24375.stderr b/tests/ui/parser/issues/issue-24375.stderr index fef3fcde7b799..03cd33f18751c 100644 --- a/tests/ui/parser/issues/issue-24375.stderr +++ b/tests/ui/parser/issues/issue-24375.stderr @@ -4,7 +4,7 @@ error: expected a pattern, found an expression LL | tmp[0] => {} | ^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == tmp[0] => {} diff --git a/tests/ui/parser/pat-lt-bracket-5.stderr b/tests/ui/parser/pat-lt-bracket-5.stderr index a2a972652d188..c68aefa0546d3 100644 --- a/tests/ui/parser/pat-lt-bracket-5.stderr +++ b/tests/ui/parser/pat-lt-bracket-5.stderr @@ -4,7 +4,7 @@ error: expected a pattern, found an expression LL | let v[0] = v[1]; | ^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: error[E0425]: cannot find value `v` in this scope --> $DIR/pat-lt-bracket-5.rs:2:16 diff --git a/tests/ui/parser/pat-lt-bracket-6.stderr b/tests/ui/parser/pat-lt-bracket-6.stderr index 14ae602fedfa1..0274809f800c5 100644 --- a/tests/ui/parser/pat-lt-bracket-6.stderr +++ b/tests/ui/parser/pat-lt-bracket-6.stderr @@ -4,7 +4,7 @@ error: expected a pattern, found an expression LL | let Test(&desc[..]) = x; | ^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: error[E0308]: mismatched types --> $DIR/pat-lt-bracket-6.rs:10:30 diff --git a/tests/ui/parser/pat-ranges-3.stderr b/tests/ui/parser/pat-ranges-3.stderr index ef080368e19ca..fcda924d98c51 100644 --- a/tests/ui/parser/pat-ranges-3.stderr +++ b/tests/ui/parser/pat-ranges-3.stderr @@ -4,7 +4,7 @@ error: expected a pattern range bound, found an expression LL | let 10 ..= 10 + 3 = 12; | ^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: error: expected a pattern range bound, found an expression --> $DIR/pat-ranges-3.rs:7:9 @@ -12,7 +12,7 @@ error: expected a pattern range bound, found an expression LL | let 10 - 3 ..= 10 = 8; | ^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: error: aborting due to 2 previous errors diff --git a/tests/ui/parser/recover/recover-pat-exprs.stderr b/tests/ui/parser/recover/recover-pat-exprs.stderr index 6cb3753de8d17..041dfd647ad07 100644 --- a/tests/ui/parser/recover/recover-pat-exprs.stderr +++ b/tests/ui/parser/recover/recover-pat-exprs.stderr @@ -4,7 +4,7 @@ error: expected a pattern, found an expression LL | x.y => (), | ^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x.y => (), @@ -27,7 +27,7 @@ error: expected a pattern, found an expression LL | x.0 => (), | ^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x.0 => (), @@ -51,7 +51,7 @@ error: expected a pattern, found an expression LL | x._0 => (), | ^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x._0 => (), @@ -76,7 +76,7 @@ error: expected a pattern, found an expression LL | x.0.1 => (), | ^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x.0.1 => (), @@ -101,7 +101,7 @@ error: expected a pattern, found an expression LL | x.4.y.17.__z => (), | ^^^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x.4.y.17.__z => (), @@ -156,7 +156,7 @@ error: expected a pattern, found an expression LL | x[0] => (), | ^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x[0] => (), @@ -178,7 +178,7 @@ error: expected a pattern, found an expression LL | x[..] => (), | ^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x[..] => (), @@ -228,7 +228,7 @@ error: expected a pattern, found an expression LL | x.f() => (), | ^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x.f() => (), @@ -250,7 +250,7 @@ error: expected a pattern, found an expression LL | x._f() => (), | ^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x._f() => (), @@ -273,7 +273,7 @@ error: expected a pattern, found an expression LL | x? => (), | ^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x? => (), @@ -297,7 +297,7 @@ error: expected a pattern, found an expression LL | ().f() => (), | ^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == ().f() => (), @@ -322,7 +322,7 @@ error: expected a pattern, found an expression LL | (0, x)?.f() => (), | ^^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == (0, x)?.f() => (), @@ -347,7 +347,7 @@ error: expected a pattern, found an expression LL | x.f().g() => (), | ^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x.f().g() => (), @@ -372,7 +372,7 @@ error: expected a pattern, found an expression LL | 0.f()?.g()?? => (), | ^^^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == 0.f()?.g()?? => (), @@ -397,7 +397,7 @@ error: expected a pattern, found an expression LL | x as usize => (), | ^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x as usize => (), @@ -419,7 +419,7 @@ error: expected a pattern, found an expression LL | 0 as usize => (), | ^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == 0 as usize => (), @@ -442,7 +442,7 @@ error: expected a pattern, found an expression LL | x.f().0.4 as f32 => (), | ^^^^^^^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x.f().0.4 as f32 => (), @@ -466,7 +466,7 @@ error: expected a pattern, found an expression LL | 1 + 1 => (), | ^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == 1 + 1 => (), @@ -488,7 +488,7 @@ error: expected a pattern, found an expression LL | (1 + 2) * 3 => (), | ^^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == (1 + 2) * 3 => (), @@ -511,7 +511,7 @@ error: expected a pattern, found an expression LL | x.0 > 2 => (), | ^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == (x.0 > 2) => (), @@ -536,7 +536,7 @@ error: expected a pattern, found an expression LL | x.0 == 2 => (), | ^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == (x.0 == 2) => (), @@ -561,7 +561,7 @@ error: expected a pattern, found an expression LL | (x, y.0 > 2) if x != 0 => (), | ^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to the match arm guard | LL | (x, val) if x != 0 && val == (y.0 > 2) => (), @@ -583,7 +583,7 @@ error: expected a pattern, found an expression LL | (x, y.0 > 2) if x != 0 || x != 1 => (), | ^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to the match arm guard | LL | (x, val) if (x != 0 || x != 1) && val == (y.0 > 2) => (), @@ -623,7 +623,7 @@ error: expected a pattern, found an expression LL | u8::MAX.abs() => (), | ^^^^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == u8::MAX.abs() => (), @@ -645,7 +645,7 @@ error: expected a pattern, found an expression LL | z @ w @ v.u() => (), | ^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | z @ w @ val if val == v.u() => (), @@ -670,7 +670,7 @@ error: expected a pattern, found an expression LL | y.ilog(3) => (), | ^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == y.ilog(3) => (), @@ -695,7 +695,7 @@ error: expected a pattern, found an expression LL | n + 1 => (), | ^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == n + 1 => (), @@ -720,7 +720,7 @@ error: expected a pattern, found an expression LL | ("".f() + 14 * 8) => (), | ^^^^^^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | (val) if val == "".f() + 14 * 8 => (), @@ -745,7 +745,7 @@ error: expected a pattern, found an expression LL | f?() => (), | ^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == f?() => (), @@ -770,7 +770,7 @@ error: expected a pattern, found an expression LL | let 1 + 1 = 2; | ^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: error: expected one of `)`, `,`, `@`, or `|`, found `*` --> $DIR/recover-pat-exprs.rs:104:28 @@ -787,7 +787,7 @@ error: expected a pattern, found an expression LL | (1 + 2) * 3 => (), | ^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:75:5 @@ -795,7 +795,7 @@ error: expected a pattern, found an expression LL | 1 + 2 * PI.cos() => 2, | ^^^^^^^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:83:9 @@ -803,7 +803,7 @@ error: expected a pattern, found an expression LL | x.sqrt() @ .. => (), | ^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: error: aborting due to 45 previous errors diff --git a/tests/ui/parser/recover/recover-pat-issues.stderr b/tests/ui/parser/recover/recover-pat-issues.stderr index 17cb7b4aead80..bdd0b2b260e7f 100644 --- a/tests/ui/parser/recover/recover-pat-issues.stderr +++ b/tests/ui/parser/recover/recover-pat-issues.stderr @@ -4,7 +4,7 @@ error: expected a pattern, found an expression LL | Foo("hi".to_owned()) => true, | ^^^^^^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | Foo(val) if val == "hi".to_owned() => true, @@ -26,7 +26,7 @@ error: expected a pattern, found an expression LL | Bar { baz: "hi".to_owned() } => true, | ^^^^^^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | Bar { baz } if baz == "hi".to_owned() => true, @@ -48,7 +48,7 @@ error: expected a pattern, found an expression LL | &["foo".to_string()] => {} | ^^^^^^^^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | &[val] if val == "foo".to_string() => {} @@ -70,7 +70,7 @@ error: expected a pattern, found an expression LL | if let Some(MAGIC.0 as usize) = None:: {} | ^^^^^^^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = MAGIC.0 as usize; @@ -87,7 +87,7 @@ error: expected a pattern, found an expression LL | if let (-1.some(4)) = (0, Some(4)) {} | ^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = -1.some(4); @@ -104,7 +104,7 @@ error: expected a pattern, found an expression LL | if let (-1.Some(4)) = (0, Some(4)) {} | ^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = -1.Some(4); diff --git a/tests/ui/parser/recover/recover-pat-lets.stderr b/tests/ui/parser/recover/recover-pat-lets.stderr index b481813b24621..55252729d7baa 100644 --- a/tests/ui/parser/recover/recover-pat-lets.stderr +++ b/tests/ui/parser/recover/recover-pat-lets.stderr @@ -4,7 +4,7 @@ error: expected a pattern, found an expression LL | let x.expect("foo"); | ^^^^^^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: error: expected a pattern, found an expression --> $DIR/recover-pat-lets.rs:7:9 @@ -12,7 +12,7 @@ error: expected a pattern, found an expression LL | let x.unwrap(): u32; | ^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: error: expected a pattern, found an expression --> $DIR/recover-pat-lets.rs:10:9 @@ -20,7 +20,7 @@ error: expected a pattern, found an expression LL | let x[0] = 1; | ^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: error: expected a pattern, found an expression --> $DIR/recover-pat-lets.rs:13:14 @@ -28,7 +28,7 @@ error: expected a pattern, found an expression LL | let Some(1 + 1) = x else { | ^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 1 + 1; @@ -45,7 +45,7 @@ error: expected a pattern, found an expression LL | if let Some(1 + 1) = x { | ^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 1 + 1; diff --git a/tests/ui/parser/recover/recover-pat-ranges.stderr b/tests/ui/parser/recover/recover-pat-ranges.stderr index 0a9b54474689a..e8f323596d0fa 100644 --- a/tests/ui/parser/recover/recover-pat-ranges.stderr +++ b/tests/ui/parser/recover/recover-pat-ranges.stderr @@ -88,7 +88,7 @@ error: expected a pattern range bound, found an expression LL | ..=1 + 2 => (), | ^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 1 + 2; @@ -109,7 +109,7 @@ error: expected a pattern range bound, found an expression LL | (-4 + 0).. => (), | ^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = -4 + 0; @@ -130,7 +130,7 @@ error: expected a pattern range bound, found an expression LL | (1 + 4)...1 * 2 => (), | ^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 1 + 4; @@ -151,7 +151,7 @@ error: expected a pattern range bound, found an expression LL | (1 + 4)...1 * 2 => (), | ^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 1 * 2; @@ -172,7 +172,7 @@ error: expected a pattern range bound, found an expression LL | 0.x()..="y".z() => (), | ^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 0.x(); @@ -193,7 +193,7 @@ error: expected a pattern range bound, found an expression LL | 0.x()..="y".z() => (), | ^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = "y".z(); diff --git a/tests/ui/parser/recover/recover-pat-wildcards.stderr b/tests/ui/parser/recover/recover-pat-wildcards.stderr index 8d4212ed389dd..81a9920f6a243 100644 --- a/tests/ui/parser/recover/recover-pat-wildcards.stderr +++ b/tests/ui/parser/recover/recover-pat-wildcards.stderr @@ -77,7 +77,7 @@ error: expected a pattern range bound, found an expression LL | 4..=(2 + _) => () | ^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 2 + _; diff --git a/tests/ui/parser/recover/recover-range-pats.stderr b/tests/ui/parser/recover/recover-range-pats.stderr index b8e91c2344aff..5c134bd4a82ab 100644 --- a/tests/ui/parser/recover/recover-range-pats.stderr +++ b/tests/ui/parser/recover/recover-range-pats.stderr @@ -613,7 +613,7 @@ LL | mac2!(0, 1); | ----------- in this macro invocation | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -627,7 +627,7 @@ LL | mac2!(0, 1); | ----------- in this macro invocation | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -641,7 +641,7 @@ LL | mac2!(0, 1); | ----------- in this macro invocation | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -655,7 +655,7 @@ LL | mac!(0); | ------- in this macro invocation | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -669,7 +669,7 @@ LL | mac!(0); | ------- in this macro invocation | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -683,7 +683,7 @@ LL | mac!(0); | ------- in this macro invocation | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -697,7 +697,7 @@ LL | mac!(0); | ------- in this macro invocation | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -711,7 +711,7 @@ LL | mac!(0); | ------- in this macro invocation | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -725,7 +725,7 @@ LL | mac!(0); | ------- in this macro invocation | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/pattern/fn-in-pat.stderr b/tests/ui/pattern/fn-in-pat.stderr index 41ea4df72a2ff..90b1dff32ce56 100644 --- a/tests/ui/pattern/fn-in-pat.stderr +++ b/tests/ui/pattern/fn-in-pat.stderr @@ -4,7 +4,7 @@ error[E0164]: expected tuple struct or tuple variant, found associated function LL | A::new() => (), | ^^^^^^^^ `fn` calls are not allowed in patterns | - = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html + = help: for more information, visit https://doc.rust-lang.org/book/ch19-00-patterns.html error: aborting due to 1 previous error diff --git a/tests/ui/pattern/issue-106552.stderr b/tests/ui/pattern/issue-106552.stderr index 96f3d68458fa4..6d9a989f182ea 100644 --- a/tests/ui/pattern/issue-106552.stderr +++ b/tests/ui/pattern/issue-106552.stderr @@ -5,7 +5,7 @@ LL | let 5 = 6; | ^ patterns `i32::MIN..=4_i32` and `6_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | @@ -23,7 +23,7 @@ LL | let x @ 5 = 6; | ^ patterns `i32::MIN..=4_i32` and `6_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` help: you might want to use `let else` to handle the variants that aren't matched | diff --git a/tests/ui/pattern/pattern-binding-disambiguation.stderr b/tests/ui/pattern/pattern-binding-disambiguation.stderr index 61c32b6a17bdf..3ba63b4d253c4 100644 --- a/tests/ui/pattern/pattern-binding-disambiguation.stderr +++ b/tests/ui/pattern/pattern-binding-disambiguation.stderr @@ -87,7 +87,7 @@ LL | let UnitVariant = UnitVariant; | ^^^^^^^^^^^ patterns `E::TupleVariant` and `E::BracedVariant { }` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html note: `E` defined here --> $DIR/pattern-binding-disambiguation.rs:5:6 | diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr index ec08e22e2ca07..4a435bcc8bad9 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr @@ -54,7 +54,7 @@ LL | let None = *x; | ^^^^ pattern `Some(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: pattern `Some(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future = note: the matched value is of type `Option` help: you might want to use `if let` to ignore the variant that isn't matched diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr index ec08e22e2ca07..4a435bcc8bad9 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr @@ -54,7 +54,7 @@ LL | let None = *x; | ^^^^ pattern `Some(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: pattern `Some(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future = note: the matched value is of type `Option` help: you might want to use `if let` to ignore the variant that isn't matched diff --git a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr index c6e41c1875fa7..23821decd6e43 100644 --- a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr @@ -150,7 +150,7 @@ LL | let Ok(_x) = res_u32_never.as_ref(); | ^^^^^^ pattern `Err(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `Result<&u32, &!>` help: you might want to use `let else` to handle the variant that isn't matched | diff --git a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr index 2e5511527d59c..cf37bf67e860b 100644 --- a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr +++ b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr @@ -126,7 +126,7 @@ LL | let Ok(_x) = res_u32_never.as_ref(); | ^^^^^^ pattern `Err(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `Result<&u32, &!>` help: you might want to use `let else` to handle the variant that isn't matched | @@ -140,7 +140,7 @@ LL | let Ok(_x) = &res_u32_never; | ^^^^^^ pattern `&Err(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `&Result` help: you might want to use `let else` to handle the variant that isn't matched | diff --git a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr index 3f312d46c7ee8..84aefe7d96370 100644 --- a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr +++ b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr @@ -104,7 +104,7 @@ LL | let Ok(_x) = res_u32_never.as_ref(); | ^^^^^^ pattern `Err(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `Result<&u32, &!>` help: you might want to use `let else` to handle the variant that isn't matched | @@ -118,7 +118,7 @@ LL | let Ok(_x) = &res_u32_never; | ^^^^^^ pattern `&Err(!)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `&Result` help: you might want to use `let else` to handle the variant that isn't matched | @@ -239,7 +239,7 @@ LL | let Ok(_) = *ptr_result_never_err; | ^^^^^ pattern `Err(!)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `Result` help: you might want to use `if let` to ignore the variant that isn't matched | diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr index bba50dab27b04..f3af74c16c30f 100644 --- a/tests/ui/pattern/usefulness/empty-types.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr @@ -95,7 +95,7 @@ LL | let Ok(_x) = res_u32_never.as_ref(); | ^^^^^^ pattern `Err(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `Result<&u32, &!>` help: you might want to use `let else` to handle the variant that isn't matched | @@ -109,7 +109,7 @@ LL | let Ok(_x) = &res_u32_never; | ^^^^^^ pattern `&Err(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `&Result` help: you might want to use `let else` to handle the variant that isn't matched | @@ -230,7 +230,7 @@ LL | let Ok(_) = *ptr_result_never_err; | ^^^^^ pattern `Err(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `Result` help: you might want to use `if let` to ignore the variant that isn't matched | diff --git a/tests/ui/pattern/usefulness/issue-31561.stderr b/tests/ui/pattern/usefulness/issue-31561.stderr index cc72056582844..ba7ae3fa9a003 100644 --- a/tests/ui/pattern/usefulness/issue-31561.stderr +++ b/tests/ui/pattern/usefulness/issue-31561.stderr @@ -5,7 +5,7 @@ LL | let Thing::Foo(y) = Thing::Foo(1); | ^^^^^^^^^^^^^ patterns `Thing::Bar` and `Thing::Baz` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html note: `Thing` defined here --> $DIR/issue-31561.rs:1:6 | diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs index 1d1ea8e496466..d0a8a10f2f371 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs +++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs @@ -44,7 +44,7 @@ fn by_val(e: E) { //~^ ERROR refutable pattern in local binding //~| patterns `E::B` and `E::C` not covered //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with - //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html //~| NOTE the matched value is of type `E` } @@ -60,7 +60,7 @@ fn by_ref_once(e: &E) { //~^ ERROR refutable pattern in local binding //~| patterns `&E::B` and `&E::C` not covered //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with - //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html //~| NOTE the matched value is of type `&E` } @@ -76,7 +76,7 @@ fn by_ref_thrice(e: & &mut &E) { //~^ ERROR refutable pattern in local binding //~| patterns `&&mut &E::B` and `&&mut &E::C` not covered //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with - //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html //~| NOTE the matched value is of type `&&mut &E` } @@ -103,7 +103,7 @@ fn ref_pat(e: Opt) { //~| NOTE the matched value is of type `Opt` //~| NOTE pattern `Opt::None` not covered //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with - //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html } fn main() {} diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr index a9e55fa53a68e..48d7a636055dc 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr @@ -29,7 +29,7 @@ LL | let E::A = e; | ^^^^ patterns `E::B` and `E::C` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html note: `E` defined here --> $DIR/non-exhaustive-defined-here.rs:8:6 | @@ -78,7 +78,7 @@ LL | let E::A = e; | ^^^^ patterns `&E::B` and `&E::C` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html note: `E` defined here --> $DIR/non-exhaustive-defined-here.rs:8:6 | @@ -127,7 +127,7 @@ LL | let E::A = e; | ^^^^ patterns `&&mut &E::B` and `&&mut &E::C` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html note: `E` defined here --> $DIR/non-exhaustive-defined-here.rs:8:6 | @@ -173,7 +173,7 @@ LL | let Opt::Some(ref _x) = e; | ^^^^^^^^^^^^^^^^^ pattern `Opt::None` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html note: `Opt` defined here --> $DIR/non-exhaustive-defined-here.rs:83:6 | diff --git a/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr b/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr index e66cd11302387..23a5d895d6c1a 100644 --- a/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr +++ b/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr @@ -13,7 +13,7 @@ LL | let (1, (Some(1), 2..=3)) = (1, (None, 2)); | ^^^^^^^^^^^^^^^^^^^^^ patterns `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `(i32, (Option, i32))` help: you might want to use `if let` to ignore the variants that aren't matched | diff --git a/tests/ui/recursion/recursive-types-are-not-uninhabited.stderr b/tests/ui/recursion/recursive-types-are-not-uninhabited.stderr index 5abec88eeff00..35d436a1413ed 100644 --- a/tests/ui/recursion/recursive-types-are-not-uninhabited.stderr +++ b/tests/ui/recursion/recursive-types-are-not-uninhabited.stderr @@ -5,7 +5,7 @@ LL | let Ok(x) = res; | ^^^^^ pattern `Err(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `Result>` help: you might want to use `let else` to handle the variant that isn't matched | diff --git a/tests/ui/resolve/issue-10200.stderr b/tests/ui/resolve/issue-10200.stderr index 172d016c6e6c4..4b6d9b6f1dfa6 100644 --- a/tests/ui/resolve/issue-10200.stderr +++ b/tests/ui/resolve/issue-10200.stderr @@ -7,7 +7,7 @@ LL | struct Foo(bool); LL | foo(x) | ^^^ help: a tuple struct with a similar name exists (notice the capitalization): `Foo` | - = note: function calls are not allowed in patterns: + = note: function calls are not allowed in patterns: error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr index 1037033c4b74b..f89ae241f44bc 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr @@ -136,7 +136,7 @@ LL | let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit | ^^^^^^^^^^^^^^^ pattern `_` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `NonExhaustiveEnum` help: you might want to use `let else` to handle the variant that isn't matched | diff --git a/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr b/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr index d40e98224355b..eec2f5b42fda9 100644 --- a/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr +++ b/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr @@ -4,7 +4,7 @@ error: expected a pattern, found an expression LL | let str::<{fn str() { let str::T>>::as_bytes; }}, T>::as_bytes; | ^^^^^^^^^^^^^^^^^^ not a pattern | - = note: arbitrary expressions are not allowed in patterns: + = note: arbitrary expressions are not allowed in patterns: error[E0412]: cannot find type `T` in this scope --> $DIR/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs:2:55 diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr index a275d8e4e8397..4f92d3aceefe0 100644 --- a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr +++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr @@ -8,7 +8,7 @@ LL | const A: i32 = 2; | ------------ missing patterns are not covered because `A` is interpreted as a constant pattern, not a new variable | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` help: introduce a variable instead | diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr index 50f33607c06f5..0e87f14aa14ae 100644 --- a/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr +++ b/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr @@ -5,7 +5,7 @@ LL | let Foo::D(_y, _z) = x; | ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html note: `Foo` defined here --> $DIR/uninhabited-irrefutable.rs:19:6 | diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr index bc1a9fa41915a..67527ce1ac452 100644 --- a/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr +++ b/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr @@ -5,7 +5,7 @@ LL | let Foo::D(_y, _z) = x; | ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html note: `Foo` defined here --> $DIR/uninhabited-irrefutable.rs:20:6 | diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.normal.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.normal.stderr index 50f33607c06f5..0e87f14aa14ae 100644 --- a/tests/ui/uninhabited/uninhabited-irrefutable.normal.stderr +++ b/tests/ui/uninhabited/uninhabited-irrefutable.normal.stderr @@ -5,7 +5,7 @@ LL | let Foo::D(_y, _z) = x; | ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html note: `Foo` defined here --> $DIR/uninhabited-irrefutable.rs:19:6 | From 30f9f6049001256971d7bb329aee5d41b617d006 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 20 Nov 2024 07:59:09 -0700 Subject: [PATCH 16/20] Vendor `trpl` crate so The Book tests work offline Without this change: $ ./x test --set build.vendor=true src/doc/book # (lots of output) error: failed to select a version for the requirement `futures = "^0.3"` (locked to 0.3.30) candidate versions found which didn't match: 0.3.31, 0.3.27 location searched: directory source `/Users/chris/dev/rust-lang/rust/vendor` (which is replacing registry `crates-io`) required by package `trpl v0.2.0 (/Users/chris/dev/rust-lang/rust/src/doc/book/packages/trpl)` perhaps a crate was updated and forgotten to be re-vendored? Build completed unsuccessfully in 0:01:19 With this change: $ ./x test --set build.vendor=true src/doc/book # (lots of build output) Testing stage1 mdbook src/doc/book (aarch64-apple-darwin) finished in 86.949 seconds Build completed successfully in 0:04:05 --- src/bootstrap/src/core/build_steps/vendor.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs index 82a6b4d4f28cb..7bca47ffe3c61 100644 --- a/src/bootstrap/src/core/build_steps/vendor.rs +++ b/src/bootstrap/src/core/build_steps/vendor.rs @@ -17,6 +17,7 @@ pub fn default_paths_to_vendor(builder: &Builder<'_>) -> Vec { "src/tools/rustbook/Cargo.toml", "src/tools/rustc-perf/Cargo.toml", "src/tools/opt-dist/Cargo.toml", + "src/doc/book/packages/trpl/Cargo.toml", ] { paths.push(builder.src.join(p)); } From f98d9dd334b4ff254912533d8b9b3cc4349f6f6a Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 20:45:39 +0200 Subject: [PATCH 17/20] Don't try to use confstr in Miri --- library/std/src/sys/pal/unix/os.rs | 8 +++++--- library/std/src/sys/pal/unix/os/tests.rs | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index d26a1bdef74b4..f207131ddf332 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -704,7 +704,9 @@ pub fn page_size() -> usize { // // [posix_confstr]: // https://pubs.opengroup.org/onlinepubs/9699919799/functions/confstr.html -#[cfg(target_vendor = "apple")] +// +// FIXME: Support `confstr` in Miri. +#[cfg(all(target_vendor = "apple", not(miri)))] fn confstr(key: c_int, size_hint: Option) -> io::Result { let mut buf: Vec = Vec::with_capacity(0); let mut bytes_needed_including_nul = size_hint @@ -753,7 +755,7 @@ fn confstr(key: c_int, size_hint: Option) -> io::Result { Ok(OsString::from_vec(buf)) } -#[cfg(target_vendor = "apple")] +#[cfg(all(target_vendor = "apple", not(miri)))] fn darwin_temp_dir() -> PathBuf { confstr(libc::_CS_DARWIN_USER_TEMP_DIR, Some(64)).map(PathBuf::from).unwrap_or_else(|_| { // It failed for whatever reason (there are several possible reasons), @@ -765,7 +767,7 @@ fn darwin_temp_dir() -> PathBuf { pub fn temp_dir() -> PathBuf { crate::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| { cfg_if::cfg_if! { - if #[cfg(target_vendor = "apple")] { + if #[cfg(all(target_vendor = "apple", not(miri)))] { darwin_temp_dir() } else if #[cfg(target_os = "android")] { PathBuf::from("/data/local/tmp") diff --git a/library/std/src/sys/pal/unix/os/tests.rs b/library/std/src/sys/pal/unix/os/tests.rs index a84086037ce0b..63a1cc1e94a1d 100644 --- a/library/std/src/sys/pal/unix/os/tests.rs +++ b/library/std/src/sys/pal/unix/os/tests.rs @@ -25,7 +25,7 @@ fn test_parse_glibc_version() { // Smoke check `confstr`, do it for several hint values, to ensure our resizing // logic is correct. #[test] -#[cfg(target_vendor = "apple")] +#[cfg(all(target_vendor = "apple", not(miri)))] fn test_confstr() { for key in [libc::_CS_DARWIN_USER_TEMP_DIR, libc::_CS_PATH] { let value_nohint = super::confstr(key, None).unwrap_or_else(|e| { From 30c7df626070db0c4395130b7fd704315fd7059e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 20 Nov 2024 18:18:29 +0100 Subject: [PATCH 18/20] Improve code by using `unsigned_abs` --- library/core/src/fmt/num.rs | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 01b5d46a8f696..4c2dfc6aa0c49 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -219,29 +219,13 @@ macro_rules! impl_Display { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for $signed { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let is_nonnegative = *self >= 0; - - if !is_nonnegative { - #[cfg(not(feature = "optimize_for_size"))] - { - // convert the negative num to positive by summing 1 to its 2s complement - return (!self as $unsigned).wrapping_add(1)._fmt(false, f); - } - #[cfg(feature = "optimize_for_size")] - { - // convert the negative num to positive by summing 1 to its 2s complement - return $gen_name((!self.$conv_fn()).wrapping_add(1), false, f); - } - } - - // If it's a positive integer. #[cfg(not(feature = "optimize_for_size"))] { - (*self as $unsigned)._fmt(true, f) + return self.unsigned_abs()._fmt(*self >= 0, f); } #[cfg(feature = "optimize_for_size")] { - $gen_name(self.$conv_fn(), true, f) + return $gen_name((!self.unsigned_abs().$conv_fn()), *self >= 0, f); } } } From 7540306a4994df05e4aca27130b2757e55000ac7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 11 Nov 2024 17:36:18 +0000 Subject: [PATCH 19/20] Simplify logic a bit --- compiler/rustc_middle/src/ty/print/pretty.rs | 181 +++++++----------- compiler/rustc_type_ir/src/predicate.rs | 13 -- .../opaque-used-in-extraneous-argument.stderr | 2 +- 3 files changed, 69 insertions(+), 127 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 039c988f5c972..5de089ee014d2 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -16,8 +16,8 @@ use rustc_hir::definitions::{DefKey, DefPathDataName}; use rustc_macros::{Lift, extension}; use rustc_session::Limit; use rustc_session::cstore::{ExternCrate, ExternCrateSource}; -use rustc_span::FileNameDisplayPreference; use rustc_span::symbol::{Ident, Symbol, kw}; +use rustc_span::{FileNameDisplayPreference, sym}; use rustc_type_ir::{Upcast as _, elaborate}; use smallvec::SmallVec; @@ -26,8 +26,8 @@ use super::*; use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar}; use crate::query::{IntoQueryParam, Providers}; use crate::ty::{ - ConstInt, Expr, GenericArgKind, ParamConst, ScalarInt, Term, TermKind, TypeFoldable, - TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + ConstInt, Expr, GenericArgKind, ParamConst, ScalarInt, Term, TermKind, TraitPredicate, + TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; macro_rules! p { @@ -1007,24 +1007,22 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } self.insert_trait_and_projection( - trait_ref, - pred.polarity, + bound_predicate.rebind(pred), None, &mut traits, &mut fn_traits, ); } ty::ClauseKind::Projection(pred) => { - let proj_ref = bound_predicate.rebind(pred); - let trait_ref = proj_ref.required_poly_trait_ref(tcx); - - // Projection type entry -- the def-id for naming, and the ty. - let proj_ty = (proj_ref.projection_def_id(), proj_ref.term()); + let proj = bound_predicate.rebind(pred); + let trait_ref = proj.map_bound(|proj| TraitPredicate { + trait_ref: proj.projection_term.trait_ref(tcx), + polarity: ty::PredicatePolarity::Positive, + }); self.insert_trait_and_projection( trait_ref, - ty::PredicatePolarity::Positive, - Some(proj_ty), + Some((proj.projection_def_id(), proj.term())), &mut traits, &mut fn_traits, ); @@ -1042,88 +1040,63 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !has_sized_bound; - for (fn_once_trait_ref, entry) in fn_traits { + for (bound_args, entry) in fn_traits { write!(self, "{}", if first { "" } else { " + " })?; write!(self, "{}", if paren_needed { "(" } else { "" })?; - self.wrap_binder(&fn_once_trait_ref, |trait_ref, cx| { - define_scoped_cx!(cx); - // Get the (single) generic ty (the args) of this FnOnce trait ref. - let generics = tcx.generics_of(trait_ref.def_id); - let own_args = generics.own_args_no_defaults(tcx, trait_ref.args); - - match (entry.return_ty, own_args[0].expect_ty()) { - // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded - // a return type. - (Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => { - let name = if entry.fn_trait_ref.is_some() { - "Fn" - } else if entry.fn_mut_trait_ref.is_some() { - "FnMut" - } else { - "FnOnce" - }; - - p!(write("{}(", name)); + let trait_def_id = + tcx.fn_trait_kind_to_def_id(entry.kind).expect("expected Fn lang items"); - for (idx, ty) in arg_tys.tuple_fields().iter().enumerate() { - if idx > 0 { - p!(", "); - } - p!(print(ty)); - } + if let Some(return_ty) = entry.return_ty { + self.wrap_binder(&bound_args, |args, cx| { + define_scoped_cx!(cx); + p!(write("{}", tcx.item_name(trait_def_id))); + p!("("); - p!(")"); - if let Some(ty) = return_ty.skip_binder().as_type() { - if !ty.is_unit() { - p!(" -> ", print(return_ty)); - } + for (idx, ty) in args.iter().enumerate() { + if idx > 0 { + p!(", "); } - p!(write("{}", if paren_needed { ")" } else { "" })); - - first = false; + p!(print(ty)); } - // If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the - // trait_refs we collected in the OpaqueFnEntry as normal trait refs. - _ => { - if entry.has_fn_once { - traits - .entry((fn_once_trait_ref, ty::PredicatePolarity::Positive)) - .or_default() - .extend( - // Group the return ty with its def id, if we had one. - entry.return_ty.map(|ty| { - (tcx.require_lang_item(LangItem::FnOnceOutput, None), ty) - }), - ); - } - if let Some(trait_ref) = entry.fn_mut_trait_ref { - traits.entry((trait_ref, ty::PredicatePolarity::Positive)).or_default(); - } - if let Some(trait_ref) = entry.fn_trait_ref { - traits.entry((trait_ref, ty::PredicatePolarity::Positive)).or_default(); + + p!(")"); + if let Some(ty) = return_ty.skip_binder().as_type() { + if !ty.is_unit() { + p!(" -> ", print(return_ty)); } } - } + p!(write("{}", if paren_needed { ")" } else { "" })); - Ok(()) - })?; + first = false; + Ok(()) + })?; + } else { + // Otherwise, render this like a regular trait. + traits.insert( + bound_args.map_bound(|args| ty::TraitPredicate { + polarity: ty::PredicatePolarity::Positive, + trait_ref: ty::TraitRef::new(tcx, trait_def_id, [Ty::new_tup(tcx, args)]), + }), + FxIndexMap::default(), + ); + } } // Print the rest of the trait types (that aren't Fn* family of traits) - for ((trait_ref, polarity), assoc_items) in traits { + for (trait_pred, assoc_items) in traits { write!(self, "{}", if first { "" } else { " + " })?; - self.wrap_binder(&trait_ref, |trait_ref, cx| { + self.wrap_binder(&trait_pred, |trait_pred, cx| { define_scoped_cx!(cx); - if polarity == ty::PredicatePolarity::Negative { + if trait_pred.polarity == ty::PredicatePolarity::Negative { p!("!"); } - p!(print(trait_ref.print_only_trait_name())); + p!(print(trait_pred.trait_ref.print_only_trait_name())); - let generics = tcx.generics_of(trait_ref.def_id); - let own_args = generics.own_args_no_defaults(tcx, trait_ref.args); + let generics = tcx.generics_of(trait_pred.def_id()); + let own_args = generics.own_args_no_defaults(tcx, trait_pred.trait_ref.args); if !own_args.is_empty() || !assoc_items.is_empty() { let mut first = true; @@ -1230,51 +1203,37 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { /// traits map or fn_traits map, depending on if the trait is in the Fn* family of traits. fn insert_trait_and_projection( &mut self, - trait_ref: ty::PolyTraitRef<'tcx>, - polarity: ty::PredicatePolarity, + trait_pred: ty::PolyTraitPredicate<'tcx>, proj_ty: Option<(DefId, ty::Binder<'tcx, Term<'tcx>>)>, traits: &mut FxIndexMap< - (ty::PolyTraitRef<'tcx>, ty::PredicatePolarity), + ty::PolyTraitPredicate<'tcx>, FxIndexMap>>, >, - fn_traits: &mut FxIndexMap, OpaqueFnEntry<'tcx>>, + fn_traits: &mut FxIndexMap>>, OpaqueFnEntry<'tcx>>, ) { - let trait_def_id = trait_ref.def_id(); + let tcx = self.tcx(); + let trait_def_id = trait_pred.def_id(); - // If our trait_ref is FnOnce or any of its children, project it onto the parent FnOnce - // super-trait ref and record it there. - // We skip negative Fn* bounds since they can't use parenthetical notation anyway. - if polarity == ty::PredicatePolarity::Positive - && let Some(fn_once_trait) = self.tcx().lang_items().fn_once_trait() + if trait_pred.polarity() == ty::PredicatePolarity::Positive + && let Some(kind) = tcx.fn_trait_kind_from_def_id(trait_def_id) + && let ty::Tuple(types) = *trait_pred.skip_binder().trait_ref.args.type_at(1).kind() { - // If we have a FnOnce, then insert it into - if trait_def_id == fn_once_trait { - let entry = fn_traits.entry(trait_ref).or_default(); - // Optionally insert the return_ty as well. - if let Some((_, ty)) = proj_ty { - entry.return_ty = Some(ty); - } - entry.has_fn_once = true; - return; - } else if self.tcx().is_lang_item(trait_def_id, LangItem::FnMut) { - let super_trait_ref = elaborate::supertraits(self.tcx(), trait_ref) - .find(|super_trait_ref| super_trait_ref.def_id() == fn_once_trait) - .unwrap(); - - fn_traits.entry(super_trait_ref).or_default().fn_mut_trait_ref = Some(trait_ref); - return; - } else if self.tcx().is_lang_item(trait_def_id, LangItem::Fn) { - let super_trait_ref = elaborate::supertraits(self.tcx(), trait_ref) - .find(|super_trait_ref| super_trait_ref.def_id() == fn_once_trait) - .unwrap(); - - fn_traits.entry(super_trait_ref).or_default().fn_trait_ref = Some(trait_ref); - return; + let entry = fn_traits + .entry(trait_pred.rebind(types)) + .or_insert_with(|| OpaqueFnEntry { kind, return_ty: None }); + if kind.extends(entry.kind) { + entry.kind = kind; + } + if let Some((proj_def_id, proj_ty)) = proj_ty + && tcx.item_name(proj_def_id) == sym::Output + { + entry.return_ty = Some(proj_ty); } + return; } // Otherwise, just group our traits and projection types. - traits.entry((trait_ref, polarity)).or_default().extend(proj_ty); + traits.entry(trait_pred).or_default().extend(proj_ty); } fn pretty_print_inherent_projection( @@ -3415,11 +3374,7 @@ pub fn provide(providers: &mut Providers) { *providers = Providers { trimmed_def_paths, ..*providers }; } -#[derive(Default)] pub struct OpaqueFnEntry<'tcx> { - // The trait ref is already stored as a key, so just track if we have it as a real predicate - has_fn_once: bool, - fn_mut_trait_ref: Option>, - fn_trait_ref: Option>, + kind: ty::ClosureKind, return_ty: Option>>, } diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 8a8e624e72a2d..5e3a3df003843 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -684,19 +684,6 @@ impl ty::Binder> { self.skip_binder().projection_term.trait_def_id(cx) } - /// Get the trait ref required for this projection to be well formed. - /// Note that for generic associated types the predicates of the associated - /// type also need to be checked. - #[inline] - pub fn required_poly_trait_ref(&self, cx: I) -> ty::Binder> { - // Note: unlike with `TraitRef::to_poly_trait_ref()`, - // `self.0.trait_ref` is permitted to have escaping regions. - // This is because here `self` has a `Binder` and so does our - // return value, so we are preserving the number of binding - // levels. - self.map_bound(|predicate| predicate.projection_term.trait_ref(cx)) - } - pub fn term(&self) -> ty::Binder { self.map_bound(|predicate| predicate.term) } diff --git a/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr b/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr index caaac5434c56a..6f0f287fe122e 100644 --- a/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr +++ b/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr @@ -74,7 +74,7 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied --> $DIR/opaque-used-in-extraneous-argument.rs:20:5 | LL | open_parent(&old_path) - | ^^^^^^^^^^^ --------- unexpected argument of type `&impl FnOnce<{type error}, Output = {type error}> + Fn<{type error}> + 'static` + | ^^^^^^^^^^^ --------- unexpected argument of type `&impl Fn<{type error}> + FnOnce<{type error}, Output = {type error}> + 'static` | note: function defined here --> $DIR/opaque-used-in-extraneous-argument.rs:12:4 From 4c53ad5f244c840049fa706e6e334c1efc19fe7d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 11 Nov 2024 17:42:35 +0000 Subject: [PATCH 20/20] Pretty print AsyncFn traits too --- .../rustc_middle/src/middle/lang_items.rs | 11 ++++++ compiler/rustc_middle/src/ty/print/pretty.rs | 34 +++++++++++++------ .../fn-exception-target-features.stderr | 4 +-- .../async-closures/fn-exception.stderr | 8 ++--- .../async-closures/pretty-async-fn-opaque.rs | 14 ++++++++ .../pretty-async-fn-opaque.stderr | 17 ++++++++++ 6 files changed, 71 insertions(+), 17 deletions(-) create mode 100644 tests/ui/async-await/async-closures/pretty-async-fn-opaque.rs create mode 100644 tests/ui/async-await/async-closures/pretty-async-fn-opaque.stderr diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs index b20673fe8daf5..7a91bfad4836c 100644 --- a/compiler/rustc_middle/src/middle/lang_items.rs +++ b/compiler/rustc_middle/src/middle/lang_items.rs @@ -68,6 +68,17 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Given a [`ty::ClosureKind`], get the [`DefId`] of its corresponding `Fn`-family + /// trait, if it is defined. + pub fn async_fn_trait_kind_to_def_id(self, kind: ty::ClosureKind) -> Option { + let items = self.lang_items(); + match kind { + ty::ClosureKind::Fn => items.async_fn_trait(), + ty::ClosureKind::FnMut => items.async_fn_mut_trait(), + ty::ClosureKind::FnOnce => items.async_fn_once_trait(), + } + } + /// Returns `true` if `id` is a `DefId` of [`Fn`], [`FnMut`] or [`FnOnce`] traits. pub fn is_fn_trait(self, id: DefId) -> bool { self.fn_trait_kind_from_def_id(id).is_some() diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 5de089ee014d2..cd4123f0a3f56 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -993,10 +993,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { match bound_predicate.skip_binder() { ty::ClauseKind::Trait(pred) => { - let trait_ref = bound_predicate.rebind(pred.trait_ref); - // Don't print `+ Sized`, but rather `+ ?Sized` if absent. - if tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized) { + if tcx.is_lang_item(pred.def_id(), LangItem::Sized) { match pred.polarity { ty::PredicatePolarity::Positive => { has_sized_bound = true; @@ -1040,12 +1038,15 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !has_sized_bound; - for (bound_args, entry) in fn_traits { + for ((bound_args, is_async), entry) in fn_traits { write!(self, "{}", if first { "" } else { " + " })?; write!(self, "{}", if paren_needed { "(" } else { "" })?; - let trait_def_id = - tcx.fn_trait_kind_to_def_id(entry.kind).expect("expected Fn lang items"); + let trait_def_id = if is_async { + tcx.async_fn_trait_kind_to_def_id(entry.kind).expect("expected AsyncFn lang items") + } else { + tcx.fn_trait_kind_to_def_id(entry.kind).expect("expected Fn lang items") + }; if let Some(return_ty) = entry.return_ty { self.wrap_binder(&bound_args, |args, cx| { @@ -1209,17 +1210,28 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ty::PolyTraitPredicate<'tcx>, FxIndexMap>>, >, - fn_traits: &mut FxIndexMap>>, OpaqueFnEntry<'tcx>>, + fn_traits: &mut FxIndexMap< + (ty::Binder<'tcx, &'tcx ty::List>>, bool), + OpaqueFnEntry<'tcx>, + >, ) { let tcx = self.tcx(); let trait_def_id = trait_pred.def_id(); + let fn_trait_and_async = if let Some(kind) = tcx.fn_trait_kind_from_def_id(trait_def_id) { + Some((kind, false)) + } else if let Some(kind) = tcx.async_fn_trait_kind_from_def_id(trait_def_id) { + Some((kind, true)) + } else { + None + }; + if trait_pred.polarity() == ty::PredicatePolarity::Positive - && let Some(kind) = tcx.fn_trait_kind_from_def_id(trait_def_id) + && let Some((kind, is_async)) = fn_trait_and_async && let ty::Tuple(types) = *trait_pred.skip_binder().trait_ref.args.type_at(1).kind() { let entry = fn_traits - .entry(trait_pred.rebind(types)) + .entry((trait_pred.rebind(types), is_async)) .or_insert_with(|| OpaqueFnEntry { kind, return_ty: None }); if kind.extends(entry.kind) { entry.kind = kind; @@ -3148,10 +3160,10 @@ define_print_and_forward_display! { TraitRefPrintSugared<'tcx> { if !with_reduced_queries() - && let Some(kind) = cx.tcx().fn_trait_kind_from_def_id(self.0.def_id) + && cx.tcx().trait_def(self.0.def_id).paren_sugar && let ty::Tuple(args) = self.0.args.type_at(1).kind() { - p!(write("{}", kind.as_str()), "("); + p!(write("{}", cx.tcx().item_name(self.0.def_id)), "("); for (i, arg) in args.iter().enumerate() { if i > 0 { p!(", "); diff --git a/tests/ui/async-await/async-closures/fn-exception-target-features.stderr b/tests/ui/async-await/async-closures/fn-exception-target-features.stderr index 396167f407055..e965c40fb5b86 100644 --- a/tests/ui/async-await/async-closures/fn-exception-target-features.stderr +++ b/tests/ui/async-await/async-closures/fn-exception-target-features.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `fn() -> Pin + 'static)>> {target_feature}: AsyncFn<()>` is not satisfied +error[E0277]: the trait bound `fn() -> Pin + 'static)>> {target_feature}: AsyncFn()` is not satisfied --> $DIR/fn-exception-target-features.rs:16:10 | LL | test(target_feature); - | ---- ^^^^^^^^^^^^^^ the trait `AsyncFn<()>` is not implemented for fn item `fn() -> Pin + 'static)>> {target_feature}` + | ---- ^^^^^^^^^^^^^^ the trait `AsyncFn()` is not implemented for fn item `fn() -> Pin + 'static)>> {target_feature}` | | | required by a bound introduced by this call | diff --git a/tests/ui/async-await/async-closures/fn-exception.stderr b/tests/ui/async-await/async-closures/fn-exception.stderr index bacd079af0f2d..20132e428332a 100644 --- a/tests/ui/async-await/async-closures/fn-exception.stderr +++ b/tests/ui/async-await/async-closures/fn-exception.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `unsafe fn() -> Pin + 'static)>> {unsafety}: AsyncFn<()>` is not satisfied +error[E0277]: the trait bound `unsafe fn() -> Pin + 'static)>> {unsafety}: AsyncFn()` is not satisfied --> $DIR/fn-exception.rs:19:10 | LL | test(unsafety); - | ---- ^^^^^^^^ the trait `AsyncFn<()>` is not implemented for fn item `unsafe fn() -> Pin + 'static)>> {unsafety}` + | ---- ^^^^^^^^ the trait `AsyncFn()` is not implemented for fn item `unsafe fn() -> Pin + 'static)>> {unsafety}` | | | required by a bound introduced by this call | @@ -12,11 +12,11 @@ note: required by a bound in `test` LL | fn test(f: impl async Fn()) {} | ^^^^^^^^^^ required by this bound in `test` -error[E0277]: the trait bound `extern "C" fn() -> Pin + 'static)>> {abi}: AsyncFn<()>` is not satisfied +error[E0277]: the trait bound `extern "C" fn() -> Pin + 'static)>> {abi}: AsyncFn()` is not satisfied --> $DIR/fn-exception.rs:20:10 | LL | test(abi); - | ---- ^^^ the trait `AsyncFn<()>` is not implemented for fn item `extern "C" fn() -> Pin + 'static)>> {abi}` + | ---- ^^^ the trait `AsyncFn()` is not implemented for fn item `extern "C" fn() -> Pin + 'static)>> {abi}` | | | required by a bound introduced by this call | diff --git a/tests/ui/async-await/async-closures/pretty-async-fn-opaque.rs b/tests/ui/async-await/async-closures/pretty-async-fn-opaque.rs new file mode 100644 index 0000000000000..2e7cf1b09fd00 --- /dev/null +++ b/tests/ui/async-await/async-closures/pretty-async-fn-opaque.rs @@ -0,0 +1,14 @@ +//@ edition: 2021 + +#![feature(async_closure)] + +use std::ops::AsyncFnMut; + +fn produce() -> impl AsyncFnMut() -> &'static str { + async || "" +} + +fn main() { + let x: i32 = produce(); + //~^ ERROR mismatched types +} diff --git a/tests/ui/async-await/async-closures/pretty-async-fn-opaque.stderr b/tests/ui/async-await/async-closures/pretty-async-fn-opaque.stderr new file mode 100644 index 0000000000000..863e61eb35ad4 --- /dev/null +++ b/tests/ui/async-await/async-closures/pretty-async-fn-opaque.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/pretty-async-fn-opaque.rs:12:18 + | +LL | fn produce() -> impl AsyncFnMut() -> &'static str { + | --------------------------------- the found opaque type +... +LL | let x: i32 = produce(); + | --- ^^^^^^^^^ expected `i32`, found opaque type + | | + | expected due to this + | + = note: expected type `i32` + found opaque type `impl AsyncFnMut() -> &'static str` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`.