From cce93f0a04ebaa4a1807f2e7f43d47839926ba94 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 30 Jan 2023 10:35:08 +0000 Subject: [PATCH 01/10] Add `str::Lines::remainder` --- library/core/src/str/iter.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index d969475aa484f..fffa421a6462a 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -1137,6 +1137,31 @@ impl<'a> DoubleEndedIterator for Lines<'a> { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Lines<'_> {} +impl<'a> Lines<'a> { + /// Returns the remaining lines of the split string. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_lines_remainder)] + /// + /// let mut lines = "a\nb\nc\nd".lines(); + /// assert_eq!(lines.remainder(), Some("a\nb\nc\nd")); + /// + /// lines.next(); + /// assert_eq!(lines.remainder(), Some("b\nc\nd")); + /// + /// lines.by_ref().for_each(drop); + /// assert_eq!(lines.remainder(), None); + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "str_lines_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.iter.remainder() + } +} + /// Created with the method [`lines_any`]. /// /// [`lines_any`]: str::lines_any From 42afefa09b30bff7699275ee5ccb33b79c54d90c Mon Sep 17 00:00:00 2001 From: Sky Date: Sun, 31 Dec 2023 00:02:08 -0500 Subject: [PATCH 02/10] Initial implementation of `str::from_raw_parts[_mut]` --- library/core/src/str/converts.rs | 40 +++++++++++++++++++++++++++++++- library/core/src/str/mod.rs | 3 +++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index 0f23cf7ae239f..ba282f09d2067 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -1,6 +1,6 @@ //! Ways to create a `str` from bytes slice. -use crate::mem; +use crate::{mem, ptr}; use super::validations::run_utf8_validation; use super::Utf8Error; @@ -205,3 +205,41 @@ pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { // comes from a reference which is guaranteed to be valid for writes. unsafe { &mut *(v as *mut [u8] as *mut str) } } + +/// Creates an `&str` from a pointer and a length. +/// +/// The pointed-to bytes must be valid UTF-8. +/// If this might not be the case, use `str::from_utf8(slice::from_raw_parts(ptr, len))`, +/// which will return an `Err` if the data isn't valid UTF-8. +/// +/// This function is the `str` equivalent of [`slice::from_raw_parts`](crate::slice::from_raw_parts). +/// See that function's documentation for safety concerns and examples. +/// +/// The mutable version of this function is [`from_raw_parts_mut`]. +#[inline] +#[must_use] +#[unstable(feature = "str_from_raw_parts", issue = "119206")] +#[rustc_const_unstable(feature = "str_from_raw_parts", issue = "119206")] +pub const unsafe fn from_raw_parts<'a>(ptr: *const u8, len: usize) -> &'a str { + // SAFETY: the caller must uphold the safety contract for `from_raw_parts`. + unsafe { &*ptr::from_raw_parts(ptr.cast(), len) } +} + +/// Creates an `&mut str` from a pointer and a length. +/// +/// The pointed-to bytes must be valid UTF-8. +/// If this might not be the case, use `str::from_utf8_mut(slice::from_raw_parts_mut(ptr, len))`, +/// which will return an `Err` if the data isn't valid UTF-8. +/// +/// This function is the `str` equivalent of [`slice::from_raw_parts_mut`](crate::slice::from_raw_parts_mut). +/// See that function's documentation for safety concerns and examples. +/// +/// The immutable version of this function is [`from_raw_parts`]. +#[inline] +#[must_use] +#[unstable(feature = "str_from_raw_parts", issue = "119206")] +#[rustc_const_unstable(feature = "const_str_from_raw_parts_mut", issue = "119206")] +pub const unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a str { + // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`. + unsafe { &mut *ptr::from_raw_parts_mut(ptr.cast(), len) } +} diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index a22c46edce254..2981d1206dd59 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -33,6 +33,9 @@ pub use converts::{from_utf8, from_utf8_unchecked}; #[stable(feature = "str_mut_extras", since = "1.20.0")] pub use converts::{from_utf8_mut, from_utf8_unchecked_mut}; +#[unstable(feature = "str_from_raw_parts", issue = "119206")] +pub use converts::{from_raw_parts, from_raw_parts_mut}; + #[stable(feature = "rust1", since = "1.0.0")] pub use error::{ParseBoolError, Utf8Error}; From c824399d74feee7f00e4b8d75f9dd85c633193f9 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Thu, 4 Jan 2024 13:08:38 -0800 Subject: [PATCH 03/10] Fix broken markdown in csky-unknown-linux-gnuabiv2.md --- .../rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md index a54abcb606ea7..e72bfb8bae767 100644 --- a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md +++ b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md @@ -50,6 +50,7 @@ cc = "${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc" [target.csky-unknown-linux-gnuabiv2hf] # ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN cc = "${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc" +``` ### Build From 1b9a01340b50cf015ec99519814628d6a28b7cfa Mon Sep 17 00:00:00 2001 From: Aldan Tanneo Date: Wed, 17 Jan 2024 10:47:33 +0100 Subject: [PATCH 04/10] specialize `Bytes` on `StdinLock<'_>` by using the underlying `BufReader` --- library/std/src/io/stdio.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 05b21eeb40f71..261b570dee74f 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -8,7 +8,9 @@ use crate::io::prelude::*; use crate::cell::{Cell, RefCell}; use crate::fmt; use crate::fs::File; -use crate::io::{self, BorrowedCursor, BufReader, IoSlice, IoSliceMut, LineWriter, Lines}; +use crate::io::{ + self, BorrowedCursor, BufReader, IoSlice, IoSliceMut, LineWriter, Lines, SpecReadByte, +}; use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantMutex, ReentrantMutexGuard}; use crate::sys::stdio; @@ -483,6 +485,13 @@ impl Read for StdinLock<'_> { } } +impl SpecReadByte for StdinLock<'_> { + #[inline] + fn spec_read_byte(&mut self) -> Option> { + BufReader::spec_read_byte(&mut *self.inner) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl BufRead for StdinLock<'_> { fn fill_buf(&mut self) -> io::Result<&[u8]> { From 8c2ae804e386d0e8e49233d23ce35469316eea52 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 24 Jan 2024 20:37:31 +0000 Subject: [PATCH 05/10] Don't manually resolve async closures in rustc_resolve --- compiler/rustc_resolve/src/late.rs | 29 ------------------- .../async-closures/higher-ranked.rs | 12 ++++++++ .../async-closures/higher-ranked.stderr | 17 +++++++++++ 3 files changed, 29 insertions(+), 29 deletions(-) create mode 100644 tests/ui/async-await/async-closures/higher-ranked.rs create mode 100644 tests/ui/async-await/async-closures/higher-ranked.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index abd724a6cc25c..18926463d6b04 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4424,35 +4424,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ExprKind::Type(ref _type_expr, ref _ty) => { visit::walk_expr(self, expr); } - // `async |x| ...` gets desugared to `|x| async {...}`, so we need to - // resolve the arguments within the proper scopes so that usages of them inside the - // closure are detected as upvars rather than normal closure arg usages. - // - // Similarly, `gen |x| ...` gets desugared to `|x| gen {...}`, so we handle that too. - ExprKind::Closure(box ast::Closure { - coroutine_kind: Some(_), - ref fn_decl, - ref body, - .. - }) => { - self.with_rib(ValueNS, RibKind::Normal, |this| { - this.with_label_rib(RibKind::FnOrCoroutine, |this| { - // Resolve arguments: - this.resolve_params(&fn_decl.inputs); - // No need to resolve return type -- - // the outer closure return type is `FnRetTy::Default`. - - // Now resolve the inner closure - { - // No need to resolve arguments: the inner closure has none. - // Resolve the return type: - visit::walk_fn_ret_ty(this, &fn_decl.output); - // Resolve the body - this.visit_expr(body); - } - }) - }); - } // For closures, RibKind::FnOrCoroutine is added in visit_fn ExprKind::Closure(box ast::Closure { binder: ClosureBinder::For { ref generic_params, span }, diff --git a/tests/ui/async-await/async-closures/higher-ranked.rs b/tests/ui/async-await/async-closures/higher-ranked.rs new file mode 100644 index 0000000000000..f0bdcf691ae2f --- /dev/null +++ b/tests/ui/async-await/async-closures/higher-ranked.rs @@ -0,0 +1,12 @@ +// edition:2021 + +#![feature(async_closure)] + +fn main() { + let x = async move |x: &str| { + //~^ ERROR lifetime may not live long enough + // This error is proof that the `&str` type is higher-ranked. + // This won't work until async closures are fully impl'd. + println!("{x}"); + }; +} diff --git a/tests/ui/async-await/async-closures/higher-ranked.stderr b/tests/ui/async-await/async-closures/higher-ranked.stderr new file mode 100644 index 0000000000000..fb02a15b079d7 --- /dev/null +++ b/tests/ui/async-await/async-closures/higher-ranked.stderr @@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/higher-ranked.rs:6:34 + | +LL | let x = async move |x: &str| { + | ____________________________-___-_^ + | | | | + | | | return type of closure `{async closure body@$DIR/higher-ranked.rs:6:34: 11:6}` contains a lifetime `'2` + | | let's call the lifetime of this reference `'1` +LL | | +LL | | // This error is proof that the `&str` type is higher-ranked. +LL | | // This won't work until async closures are fully impl'd. +LL | | println!("{x}"); +LL | | }; + | |_____^ returning this value requires that `'1` must outlive `'2` + +error: aborting due to 1 previous error + From 886108b9fe5b1e681f8bd8e34fdfab23cc74ef53 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 8 Jan 2024 21:48:22 +0100 Subject: [PATCH 06/10] Add feature gate --- compiler/rustc_feature/src/unstable.rs | 3 +++ compiler/rustc_span/src/symbol.rs | 1 + 2 files changed, 4 insertions(+) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 6eed2178ead8d..e66a66e23dc4f 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -516,6 +516,9 @@ declare_features! ( (unstable, macro_metavar_expr, "1.61.0", Some(83527)), /// Allows `#[marker]` on certain traits allowing overlapping implementations. (unstable, marker_trait_attr, "1.30.0", Some(29864)), + /// Allows exhaustive pattern matching on types that contain uninhabited types in cases that are + /// unambiguously sound. + (incomplete, min_exhaustive_patterns, "CURRENT_RUSTC_VERSION", Some(119612)), /// A minimal, sound subset of specialization intended to be used by the /// standard library until the soundness issues with specialization /// are fixed. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 90a38b26f73ca..4456cd1e2f852 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1023,6 +1023,7 @@ symbols! { min_const_fn, min_const_generics, min_const_unsafe_fn, + min_exhaustive_patterns, min_specialization, min_type_alias_impl_trait, minnumf32, From 95a14d43d7aa4b37a8f45a0d97d109f91f9b079f Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 18 Jan 2024 19:22:44 +0100 Subject: [PATCH 07/10] Implement feature gate logic --- compiler/rustc_pattern_analysis/src/lib.rs | 1 + compiler/rustc_pattern_analysis/src/rustc.rs | 7 +- .../rustc_pattern_analysis/src/usefulness.rs | 26 +- .../empty-types.exhaustive_patterns.stderr | 100 +-- .../empty-types.min_exh_pats.stderr | 630 ++++++++++++++++++ .../usefulness/empty-types.normal.stderr | 98 +-- tests/ui/pattern/usefulness/empty-types.rs | 84 +-- 7 files changed, 797 insertions(+), 149 deletions(-) create mode 100644 tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 4fd01b5e638ce..9311f763f67bf 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -95,6 +95,7 @@ pub trait TypeCx: Sized + fmt::Debug { type PatData: Clone; fn is_exhaustive_patterns_feature_on(&self) -> bool; + fn is_min_exhaustive_patterns_feature_on(&self) -> bool; /// The number of fields for this constructor. fn ctor_arity(&self, ctor: &Constructor, ty: &Self::Ty) -> usize; diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index d8c3c010a2a93..1971a731d27c7 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -182,7 +182,9 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { // `field.ty()` doesn't normalize after substituting. let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty); let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx); - let is_uninhabited = cx.tcx.features().exhaustive_patterns && cx.is_uninhabited(ty); + let is_uninhabited = (cx.tcx.features().exhaustive_patterns + || cx.tcx.features().min_exhaustive_patterns) + && cx.is_uninhabited(ty); if is_uninhabited && (!is_visible || is_non_exhaustive) { None @@ -960,6 +962,9 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { fn is_exhaustive_patterns_feature_on(&self) -> bool { self.tcx.features().exhaustive_patterns } + fn is_min_exhaustive_patterns_feature_on(&self) -> bool { + self.tcx.features().min_exhaustive_patterns + } fn ctor_arity(&self, ctor: &crate::constructor::Constructor, ty: &Self::Ty) -> usize { self.ctor_arity(ctor, *ty) diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index d7852a2b2cbfc..c71f375ca905b 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -548,11 +548,12 @@ //! [`ValidityConstraint::specialize`]. //! //! Having said all that, in practice we don't fully follow what's been presented in this section. -//! Under `exhaustive_patterns`, we allow omitting empty arms even in `!known_valid` places, for -//! backwards-compatibility until we have a better alternative. Without `exhaustive_patterns`, we -//! mostly treat empty types as inhabited, except specifically a non-nested `!` or empty enum. In -//! this specific case we also allow the empty match regardless of place validity, for -//! backwards-compatibility. Hopefully we can eventually deprecate this. +//! Let's call "toplevel exception" the case where the match scrutinee itself has type `!` or +//! `EmptyEnum`. First, on stable rust, we require `_` patterns for empty types in all cases apart +//! from the toplevel exception. The `exhaustive_patterns` and `min_exaustive_patterns` allow +//! omitting patterns in the cases described above. There's a final detail: in the toplevel +//! exception or with the `exhaustive_patterns` feature, we ignore place validity when checking +//! whether a pattern is required for exhaustiveness. I (Nadrieril) hope to deprecate this behavior. //! //! //! @@ -1440,10 +1441,17 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( // We treat match scrutinees of type `!` or `EmptyEnum` differently. let is_toplevel_exception = is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors); - // Whether empty patterns can be omitted for exhaustiveness. - let can_omit_empty_arms = is_toplevel_exception || mcx.tycx.is_exhaustive_patterns_feature_on(); - // Whether empty patterns are counted as useful or not. - let empty_arms_are_unreachable = place_validity.is_known_valid() && can_omit_empty_arms; + // Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if + // it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`). + let empty_arms_are_unreachable = place_validity.is_known_valid() + && (is_toplevel_exception + || mcx.tycx.is_exhaustive_patterns_feature_on() + || mcx.tycx.is_min_exhaustive_patterns_feature_on()); + // Whether empty patterns can be omitted for exhaustiveness. We ignore place validity in the + // toplevel exception and `exhaustive_patterns` cases for backwards compatibility. + let can_omit_empty_arms = empty_arms_are_unreachable + || is_toplevel_exception + || mcx.tycx.is_exhaustive_patterns_feature_on(); // Analyze the constructors present in this column. let ctors = matrix.heads().map(|p| p.ctor()); diff --git a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr index 367aba3bdd6e6..0c55164a780b5 100644 --- a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr @@ -1,23 +1,23 @@ error: unreachable pattern - --> $DIR/empty-types.rs:47:9 + --> $DIR/empty-types.rs:50:9 | LL | _ => {} | ^ | note: the lint level is defined here - --> $DIR/empty-types.rs:13:9 + --> $DIR/empty-types.rs:16:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:50:9 + --> $DIR/empty-types.rs:53:9 | LL | _x => {} | ^^ error[E0004]: non-exhaustive patterns: type `&!` is non-empty - --> $DIR/empty-types.rs:54:11 + --> $DIR/empty-types.rs:57:11 | LL | match ref_never {} | ^^^^^^^^^ @@ -32,31 +32,31 @@ LL + } | error: unreachable pattern - --> $DIR/empty-types.rs:69:9 + --> $DIR/empty-types.rs:72:9 | LL | (_, _) => {} | ^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:76:9 + --> $DIR/empty-types.rs:79:9 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:79:9 + --> $DIR/empty-types.rs:82:9 | LL | (_, _) => {} | ^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:83:9 + --> $DIR/empty-types.rs:86:9 | LL | _ => {} | ^ error[E0004]: non-exhaustive patterns: `Ok(_)` not covered - --> $DIR/empty-types.rs:87:11 + --> $DIR/empty-types.rs:90:11 | LL | match res_u32_never {} | ^^^^^^^^^^^^^ pattern `Ok(_)` not covered @@ -75,19 +75,19 @@ LL + } | error: unreachable pattern - --> $DIR/empty-types.rs:95:9 + --> $DIR/empty-types.rs:98:9 | LL | Err(_) => {} | ^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:100:9 + --> $DIR/empty-types.rs:103:9 | LL | Err(_) => {} | ^^^^^^ error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered - --> $DIR/empty-types.rs:97:11 + --> $DIR/empty-types.rs:100:11 | LL | match res_u32_never { | ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered @@ -105,7 +105,7 @@ LL ~ Ok(1_u32..=u32::MAX) => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:104:9 + --> $DIR/empty-types.rs:107:9 | LL | let Ok(_x) = res_u32_never.as_ref(); | ^^^^^^ pattern `Err(_)` not covered @@ -119,121 +119,121 @@ LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() }; | ++++++++++++++++ error: unreachable pattern - --> $DIR/empty-types.rs:115:9 + --> $DIR/empty-types.rs:118:9 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:119:9 + --> $DIR/empty-types.rs:122:9 | LL | Ok(_) => {} | ^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:122:9 + --> $DIR/empty-types.rs:125:9 | LL | Ok(_) => {} | ^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:123:9 + --> $DIR/empty-types.rs:126:9 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:126:9 + --> $DIR/empty-types.rs:129:9 | LL | Ok(_) => {} | ^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:127:9 + --> $DIR/empty-types.rs:130:9 | LL | Err(_) => {} | ^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:136:13 + --> $DIR/empty-types.rs:139:13 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:139:13 + --> $DIR/empty-types.rs:142:13 | LL | _ if false => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:148:13 + --> $DIR/empty-types.rs:151:13 | LL | Some(_) => {} | ^^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:152:13 + --> $DIR/empty-types.rs:155:13 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:204:13 + --> $DIR/empty-types.rs:207:13 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:209:13 + --> $DIR/empty-types.rs:212:13 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:214:13 + --> $DIR/empty-types.rs:217:13 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:219:13 + --> $DIR/empty-types.rs:222:13 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:225:13 + --> $DIR/empty-types.rs:228:13 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:284:9 + --> $DIR/empty-types.rs:287:9 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:287:9 + --> $DIR/empty-types.rs:290:9 | LL | (_, _) => {} | ^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:290:9 + --> $DIR/empty-types.rs:293:9 | LL | Ok(_) => {} | ^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:291:9 + --> $DIR/empty-types.rs:294:9 | LL | Err(_) => {} | ^^^^^^ error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty - --> $DIR/empty-types.rs:323:11 + --> $DIR/empty-types.rs:326:11 | LL | match slice_never {} | ^^^^^^^^^^^ @@ -247,7 +247,7 @@ LL + } | error[E0004]: non-exhaustive patterns: `&[]` not covered - --> $DIR/empty-types.rs:334:11 + --> $DIR/empty-types.rs:337:11 | LL | match slice_never { | ^^^^^^^^^^^ pattern `&[]` not covered @@ -260,7 +260,7 @@ LL + &[] => todo!() | error[E0004]: non-exhaustive patterns: `&[]` not covered - --> $DIR/empty-types.rs:347:11 + --> $DIR/empty-types.rs:350:11 | LL | match slice_never { | ^^^^^^^^^^^ pattern `&[]` not covered @@ -274,7 +274,7 @@ LL + &[] => todo!() | error[E0004]: non-exhaustive patterns: type `[!]` is non-empty - --> $DIR/empty-types.rs:353:11 + --> $DIR/empty-types.rs:356:11 | LL | match *slice_never {} | ^^^^^^^^^^^^ @@ -288,25 +288,25 @@ LL + } | error: unreachable pattern - --> $DIR/empty-types.rs:363:9 + --> $DIR/empty-types.rs:366:9 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:366:9 + --> $DIR/empty-types.rs:369:9 | LL | [_, _, _] => {} | ^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:369:9 + --> $DIR/empty-types.rs:372:9 | LL | [_, ..] => {} | ^^^^^^^ error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty - --> $DIR/empty-types.rs:383:11 + --> $DIR/empty-types.rs:386:11 | LL | match array_0_never {} | ^^^^^^^^^^^^^ @@ -320,13 +320,13 @@ LL + } | error: unreachable pattern - --> $DIR/empty-types.rs:390:9 + --> $DIR/empty-types.rs:393:9 | LL | _ => {} | ^ error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/empty-types.rs:392:11 + --> $DIR/empty-types.rs:395:11 | LL | match array_0_never { | ^^^^^^^^^^^^^ pattern `[]` not covered @@ -340,49 +340,49 @@ LL + [] => todo!() | error: unreachable pattern - --> $DIR/empty-types.rs:411:9 + --> $DIR/empty-types.rs:414:9 | LL | Some(_) => {} | ^^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:416:9 + --> $DIR/empty-types.rs:419:9 | LL | Some(_a) => {} | ^^^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:421:9 + --> $DIR/empty-types.rs:424:9 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:426:9 + --> $DIR/empty-types.rs:429:9 | LL | _a => {} | ^^ error: unreachable pattern - --> $DIR/empty-types.rs:598:9 + --> $DIR/empty-types.rs:601:9 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:601:9 + --> $DIR/empty-types.rs:604:9 | LL | _x => {} | ^^ error: unreachable pattern - --> $DIR/empty-types.rs:604:9 + --> $DIR/empty-types.rs:607:9 | LL | _ if false => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:607:9 + --> $DIR/empty-types.rs:610:9 | LL | _x if false => {} | ^^ diff --git a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr new file mode 100644 index 0000000000000..ed5d125e68404 --- /dev/null +++ b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr @@ -0,0 +1,630 @@ +warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/empty-types.rs:13:35 + | +LL | #![cfg_attr(min_exh_pats, feature(min_exhaustive_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #119612 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: unreachable pattern + --> $DIR/empty-types.rs:50:9 + | +LL | _ => {} + | ^ + | +note: the lint level is defined here + --> $DIR/empty-types.rs:16:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:53:9 + | +LL | _x => {} + | ^^ + +error[E0004]: non-exhaustive patterns: type `&!` is non-empty + --> $DIR/empty-types.rs:57:11 + | +LL | match ref_never {} + | ^^^^^^^^^ + | + = note: the matched value is of type `&!` + = note: references are always considered inhabited +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match ref_never { +LL + _ => todo!(), +LL + } + | + +error: unreachable pattern + --> $DIR/empty-types.rs:72:9 + | +LL | (_, _) => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:79:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:82:9 + | +LL | (_, _) => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:86:9 + | +LL | _ => {} + | ^ + +error[E0004]: non-exhaustive patterns: `Ok(_)` not covered + --> $DIR/empty-types.rs:90:11 + | +LL | match res_u32_never {} + | ^^^^^^^^^^^^^ pattern `Ok(_)` not covered + | +note: `Result` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result` +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 res_u32_never { +LL + Ok(_) => todo!(), +LL + } + | + +error: unreachable pattern + --> $DIR/empty-types.rs:98:9 + | +LL | Err(_) => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:103:9 + | +LL | Err(_) => {} + | ^^^^^^ + +error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered + --> $DIR/empty-types.rs:100:11 + | +LL | match res_u32_never { + | ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered + | +note: `Result` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result` +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 ~ Err(_) => {}, +LL ~ Ok(1_u32..=u32::MAX) => todo!() + | + +error[E0005]: refutable pattern in local binding + --> $DIR/empty-types.rs:107:9 + | +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: the matched value is of type `Result<&u32, &!>` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() }; + | ++++++++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/empty-types.rs:111:9 + | +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: the matched value is of type `&Result` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Ok(_x) = &res_u32_never else { todo!() }; + | ++++++++++++++++ + +error: unreachable pattern + --> $DIR/empty-types.rs:118:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:122:9 + | +LL | Ok(_) => {} + | ^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:125:9 + | +LL | Ok(_) => {} + | ^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:126:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:129:9 + | +LL | Ok(_) => {} + | ^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:130:9 + | +LL | Err(_) => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:139:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:142:13 + | +LL | _ if false => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:151:13 + | +LL | Some(_) => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:155:13 + | +LL | _ => {} + | ^ + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/empty-types.rs:164:15 + | +LL | match *ref_opt_void { + | ^^^^^^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +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 ~ None => {}, +LL + Some(_) => todo!() + | + +error: unreachable pattern + --> $DIR/empty-types.rs:207:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:212:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:217:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:222:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:228:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:287:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:290:9 + | +LL | (_, _) => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:293:9 + | +LL | Ok(_) => {} + | ^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:294:9 + | +LL | Err(_) => {} + | ^^^^^^ + +error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty + --> $DIR/empty-types.rs:315:11 + | +LL | match *x {} + | ^^ + | + = note: the matched value is of type `(u32, !)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match *x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty + --> $DIR/empty-types.rs:317:11 + | +LL | match *x {} + | ^^ + | + = note: the matched value is of type `(!, !)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match *x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered + --> $DIR/empty-types.rs:319:11 + | +LL | match *x {} + | ^^ patterns `Ok(_)` and `Err(_)` not covered + | +note: `Result` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ match *x { +LL + Ok(_) | Err(_) => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty + --> $DIR/empty-types.rs:321:11 + | +LL | match *x {} + | ^^ + | + = note: the matched value is of type `[!; 3]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match *x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty + --> $DIR/empty-types.rs:326:11 + | +LL | match slice_never {} + | ^^^^^^^^^^^ + | + = note: the matched value is of type `&[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match slice_never { +LL + _ => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered + --> $DIR/empty-types.rs:328:11 + | +LL | match slice_never { + | ^^^^^^^^^^^ pattern `&[_, ..]` not covered + | + = note: the matched value is of type `&[!]` +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 ~ [] => {}, +LL + &[_, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[]`, `&[_]` and `&[_, _]` not covered + --> $DIR/empty-types.rs:337:11 + | +LL | match slice_never { + | ^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _]` not covered + | + = note: the matched value is of type `&[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ [_, _, _, ..] => {}, +LL + &[] | &[_] | &[_, _] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered + --> $DIR/empty-types.rs:350:11 + | +LL | match slice_never { + | ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered + | + = note: the matched value is of type `&[!]` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ &[..] if false => {}, +LL + &[] | &[_, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: type `[!]` is non-empty + --> $DIR/empty-types.rs:356:11 + | +LL | match *slice_never {} + | ^^^^^^^^^^^^ + | + = note: the matched value is of type `[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match *slice_never { +LL + _ => todo!(), +LL + } + | + +error: unreachable pattern + --> $DIR/empty-types.rs:366:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:369:9 + | +LL | [_, _, _] => {} + | ^^^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:372:9 + | +LL | [_, ..] => {} + | ^^^^^^^ + +error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty + --> $DIR/empty-types.rs:386:11 + | +LL | match array_0_never {} + | ^^^^^^^^^^^^^ + | + = note: the matched value is of type `[!; 0]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match array_0_never { +LL + _ => todo!(), +LL + } + | + +error: unreachable pattern + --> $DIR/empty-types.rs:393:9 + | +LL | _ => {} + | ^ + +error[E0004]: non-exhaustive patterns: `[]` not covered + --> $DIR/empty-types.rs:395:11 + | +LL | match array_0_never { + | ^^^^^^^^^^^^^ pattern `[]` not covered + | + = note: the matched value is of type `[!; 0]` + = note: match arms with guards don't count towards exhaustivity +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 ~ [..] if false => {}, +LL + [] => todo!() + | + +error: unreachable pattern + --> $DIR/empty-types.rs:414:9 + | +LL | Some(_) => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:419:9 + | +LL | Some(_a) => {} + | ^^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:424:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:429:9 + | +LL | _a => {} + | ^^ + +error[E0004]: non-exhaustive patterns: `&Some(_)` not covered + --> $DIR/empty-types.rs:449:11 + | +LL | match ref_opt_never { + | ^^^^^^^^^^^^^ pattern `&Some(_)` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `&Option` +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 ~ &None => {}, +LL + &Some(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/empty-types.rs:490:11 + | +LL | match *ref_opt_never { + | ^^^^^^^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +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 ~ None => {}, +LL + Some(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Err(_)` not covered + --> $DIR/empty-types.rs:538:11 + | +LL | match *ref_res_never { + | ^^^^^^^^^^^^^^ pattern `Err(_)` not covered + | +note: `Result` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result` +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 ~ Ok(_) => {}, +LL + Err(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Err(_)` not covered + --> $DIR/empty-types.rs:549:11 + | +LL | match *ref_res_never { + | ^^^^^^^^^^^^^^ pattern `Err(_)` not covered + | +note: `Result` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result` +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 ~ Ok(_a) => {}, +LL + Err(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty + --> $DIR/empty-types.rs:568:11 + | +LL | match *ref_tuple_half_never {} + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the matched value is of type `(u32, !)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match *ref_tuple_half_never { +LL + _ => todo!(), +LL + } + | + +error: unreachable pattern + --> $DIR/empty-types.rs:601:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:604:9 + | +LL | _x => {} + | ^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:607:9 + | +LL | _ if false => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:610:9 + | +LL | _x if false => {} + | ^^ + +error[E0004]: non-exhaustive patterns: `&_` not covered + --> $DIR/empty-types.rs:635:11 + | +LL | match ref_never { + | ^^^^^^^^^ pattern `&_` not covered + | + = note: the matched value is of type `&!` + = note: references are always considered inhabited + = note: match arms with guards don't count towards exhaustivity +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 ~ &_a if false => {}, +LL + &_ => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/empty-types.rs:663:11 + | +LL | match *x { + | ^^ pattern `Some(_)` not covered + | +note: `Option>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option>` +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 ~ None => {}, +LL + Some(_) => todo!() + | + +error: aborting due to 63 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0004, E0005. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr index 133a95a821ba3..2fdb51677dac5 100644 --- a/tests/ui/pattern/usefulness/empty-types.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr @@ -1,23 +1,23 @@ error: unreachable pattern - --> $DIR/empty-types.rs:47:9 + --> $DIR/empty-types.rs:50:9 | LL | _ => {} | ^ | note: the lint level is defined here - --> $DIR/empty-types.rs:13:9 + --> $DIR/empty-types.rs:16:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:50:9 + --> $DIR/empty-types.rs:53:9 | LL | _x => {} | ^^ error[E0004]: non-exhaustive patterns: type `&!` is non-empty - --> $DIR/empty-types.rs:54:11 + --> $DIR/empty-types.rs:57:11 | LL | match ref_never {} | ^^^^^^^^^ @@ -32,7 +32,7 @@ LL + } | error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:66:11 + --> $DIR/empty-types.rs:69:11 | LL | match tuple_half_never {} | ^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL + } | error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty - --> $DIR/empty-types.rs:73:11 + --> $DIR/empty-types.rs:76:11 | LL | match tuple_never {} | ^^^^^^^^^^^ @@ -60,13 +60,13 @@ LL + } | error: unreachable pattern - --> $DIR/empty-types.rs:83:9 + --> $DIR/empty-types.rs:86:9 | LL | _ => {} | ^ error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered - --> $DIR/empty-types.rs:87:11 + --> $DIR/empty-types.rs:90:11 | LL | match res_u32_never {} | ^^^^^^^^^^^^^ patterns `Ok(_)` and `Err(_)` not covered @@ -88,7 +88,7 @@ LL + } | error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/empty-types.rs:89:11 + --> $DIR/empty-types.rs:92:11 | LL | match res_u32_never { | ^^^^^^^^^^^^^ pattern `Err(_)` not covered @@ -106,7 +106,7 @@ LL + Err(_) => todo!() | error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered - --> $DIR/empty-types.rs:97:11 + --> $DIR/empty-types.rs:100:11 | LL | match res_u32_never { | ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered @@ -124,7 +124,7 @@ LL ~ Ok(1_u32..=u32::MAX) => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:102:9 + --> $DIR/empty-types.rs:105:9 | LL | let Ok(_x) = res_u32_never; | ^^^^^^ pattern `Err(_)` not covered @@ -138,7 +138,7 @@ LL | let Ok(_x) = res_u32_never else { todo!() }; | ++++++++++++++++ error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:104:9 + --> $DIR/empty-types.rs:107:9 | LL | let Ok(_x) = res_u32_never.as_ref(); | ^^^^^^ pattern `Err(_)` not covered @@ -152,7 +152,7 @@ LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() }; | ++++++++++++++++ error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:108:9 + --> $DIR/empty-types.rs:111:9 | LL | let Ok(_x) = &res_u32_never; | ^^^^^^ pattern `&Err(_)` not covered @@ -166,7 +166,7 @@ LL | let Ok(_x) = &res_u32_never else { todo!() }; | ++++++++++++++++ error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered - --> $DIR/empty-types.rs:112:11 + --> $DIR/empty-types.rs:115:11 | LL | match result_never {} | ^^^^^^^^^^^^ patterns `Ok(_)` and `Err(_)` not covered @@ -188,7 +188,7 @@ LL + } | error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/empty-types.rs:117:11 + --> $DIR/empty-types.rs:120:11 | LL | match result_never { | ^^^^^^^^^^^^ pattern `Err(_)` not covered @@ -205,19 +205,19 @@ LL | Ok(_) => {}, Err(_) => todo!() | +++++++++++++++++++ error: unreachable pattern - --> $DIR/empty-types.rs:136:13 + --> $DIR/empty-types.rs:139:13 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:139:13 + --> $DIR/empty-types.rs:142:13 | LL | _ if false => {} | ^ error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:142:15 + --> $DIR/empty-types.rs:145:15 | LL | match opt_void { | ^^^^^^^^ pattern `Some(_)` not covered @@ -235,7 +235,7 @@ LL + Some(_) => todo!() | error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:161:15 + --> $DIR/empty-types.rs:164:15 | LL | match *ref_opt_void { | ^^^^^^^^^^^^^ pattern `Some(_)` not covered @@ -253,43 +253,43 @@ LL + Some(_) => todo!() | error: unreachable pattern - --> $DIR/empty-types.rs:204:13 + --> $DIR/empty-types.rs:207:13 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:209:13 + --> $DIR/empty-types.rs:212:13 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:214:13 + --> $DIR/empty-types.rs:217:13 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:219:13 + --> $DIR/empty-types.rs:222:13 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:225:13 + --> $DIR/empty-types.rs:228:13 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:284:9 + --> $DIR/empty-types.rs:287:9 | LL | _ => {} | ^ error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:312:11 + --> $DIR/empty-types.rs:315:11 | LL | match *x {} | ^^ @@ -303,7 +303,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty - --> $DIR/empty-types.rs:314:11 + --> $DIR/empty-types.rs:317:11 | LL | match *x {} | ^^ @@ -317,7 +317,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered - --> $DIR/empty-types.rs:316:11 + --> $DIR/empty-types.rs:319:11 | LL | match *x {} | ^^ patterns `Ok(_)` and `Err(_)` not covered @@ -339,7 +339,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty - --> $DIR/empty-types.rs:318:11 + --> $DIR/empty-types.rs:321:11 | LL | match *x {} | ^^ @@ -353,7 +353,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty - --> $DIR/empty-types.rs:323:11 + --> $DIR/empty-types.rs:326:11 | LL | match slice_never {} | ^^^^^^^^^^^ @@ -367,7 +367,7 @@ LL + } | error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered - --> $DIR/empty-types.rs:325:11 + --> $DIR/empty-types.rs:328:11 | LL | match slice_never { | ^^^^^^^^^^^ pattern `&[_, ..]` not covered @@ -380,7 +380,7 @@ LL + &[_, ..] => todo!() | error[E0004]: non-exhaustive patterns: `&[]`, `&[_]` and `&[_, _]` not covered - --> $DIR/empty-types.rs:334:11 + --> $DIR/empty-types.rs:337:11 | LL | match slice_never { | ^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _]` not covered @@ -393,7 +393,7 @@ LL + &[] | &[_] | &[_, _] => todo!() | error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered - --> $DIR/empty-types.rs:347:11 + --> $DIR/empty-types.rs:350:11 | LL | match slice_never { | ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered @@ -407,7 +407,7 @@ LL + &[] | &[_, ..] => todo!() | error[E0004]: non-exhaustive patterns: type `[!]` is non-empty - --> $DIR/empty-types.rs:353:11 + --> $DIR/empty-types.rs:356:11 | LL | match *slice_never {} | ^^^^^^^^^^^^ @@ -421,7 +421,7 @@ LL + } | error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty - --> $DIR/empty-types.rs:360:11 + --> $DIR/empty-types.rs:363:11 | LL | match array_3_never {} | ^^^^^^^^^^^^^ @@ -435,7 +435,7 @@ LL + } | error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty - --> $DIR/empty-types.rs:383:11 + --> $DIR/empty-types.rs:386:11 | LL | match array_0_never {} | ^^^^^^^^^^^^^ @@ -449,13 +449,13 @@ LL + } | error: unreachable pattern - --> $DIR/empty-types.rs:390:9 + --> $DIR/empty-types.rs:393:9 | LL | _ => {} | ^ error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/empty-types.rs:392:11 + --> $DIR/empty-types.rs:395:11 | LL | match array_0_never { | ^^^^^^^^^^^^^ pattern `[]` not covered @@ -469,7 +469,7 @@ LL + [] => todo!() | error[E0004]: non-exhaustive patterns: `&Some(_)` not covered - --> $DIR/empty-types.rs:446:11 + --> $DIR/empty-types.rs:449:11 | LL | match ref_opt_never { | ^^^^^^^^^^^^^ pattern `&Some(_)` not covered @@ -487,7 +487,7 @@ LL + &Some(_) => todo!() | error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:487:11 + --> $DIR/empty-types.rs:490:11 | LL | match *ref_opt_never { | ^^^^^^^^^^^^^^ pattern `Some(_)` not covered @@ -505,7 +505,7 @@ LL + Some(_) => todo!() | error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/empty-types.rs:535:11 + --> $DIR/empty-types.rs:538:11 | LL | match *ref_res_never { | ^^^^^^^^^^^^^^ pattern `Err(_)` not covered @@ -523,7 +523,7 @@ LL + Err(_) => todo!() | error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/empty-types.rs:546:11 + --> $DIR/empty-types.rs:549:11 | LL | match *ref_res_never { | ^^^^^^^^^^^^^^ pattern `Err(_)` not covered @@ -541,7 +541,7 @@ LL + Err(_) => todo!() | error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:565:11 + --> $DIR/empty-types.rs:568:11 | LL | match *ref_tuple_half_never {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -555,31 +555,31 @@ LL + } | error: unreachable pattern - --> $DIR/empty-types.rs:598:9 + --> $DIR/empty-types.rs:601:9 | LL | _ => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:601:9 + --> $DIR/empty-types.rs:604:9 | LL | _x => {} | ^^ error: unreachable pattern - --> $DIR/empty-types.rs:604:9 + --> $DIR/empty-types.rs:607:9 | LL | _ if false => {} | ^ error: unreachable pattern - --> $DIR/empty-types.rs:607:9 + --> $DIR/empty-types.rs:610:9 | LL | _x if false => {} | ^^ error[E0004]: non-exhaustive patterns: `&_` not covered - --> $DIR/empty-types.rs:631:11 + --> $DIR/empty-types.rs:635:11 | LL | match ref_never { | ^^^^^^^^^ pattern `&_` not covered @@ -594,7 +594,7 @@ LL + &_ => todo!() | error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:659:11 + --> $DIR/empty-types.rs:663:11 | LL | match *x { | ^^ pattern `Some(_)` not covered diff --git a/tests/ui/pattern/usefulness/empty-types.rs b/tests/ui/pattern/usefulness/empty-types.rs index 1e1d23e446d4c..c66fd1edc19ec 100644 --- a/tests/ui/pattern/usefulness/empty-types.rs +++ b/tests/ui/pattern/usefulness/empty-types.rs @@ -1,4 +1,5 @@ -// revisions: normal exhaustive_patterns +// revisions: normal min_exh_pats exhaustive_patterns +// gate-test-min_exhaustive_patterns // // This tests correct handling of empty types in exhaustiveness checking. // @@ -9,6 +10,8 @@ // This feature is useful to avoid `!` falling back to `()` all the time. #![feature(never_type_fallback)] #![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exh_pats, feature(min_exhaustive_patterns))] +//[min_exh_pats]~^ WARN the feature `min_exhaustive_patterns` is incomplete #![allow(dead_code, unreachable_code)] #![deny(unreachable_patterns)] @@ -66,17 +69,17 @@ fn basic(x: NeverBundle) { match tuple_half_never {} //[normal]~^ ERROR non-empty match tuple_half_never { - (_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + (_, _) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } let tuple_never: (!, !) = x.tuple_never; match tuple_never {} //[normal]~^ ERROR non-empty match tuple_never { - _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern + _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } match tuple_never { - (_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + (_, _) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } match tuple_never.0 {} match tuple_never.0 { @@ -92,12 +95,12 @@ fn basic(x: NeverBundle) { } match res_u32_never { Ok(_) => {} - Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } match res_u32_never { //~^ ERROR non-exhaustive Ok(0) => {} - Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } let Ok(_x) = res_u32_never; //[normal]~^ ERROR refutable @@ -106,25 +109,25 @@ fn basic(x: NeverBundle) { // Non-obvious difference: here there's an implicit dereference in the patterns, which makes the // inner place !known_valid. `exhaustive_patterns` ignores this. let Ok(_x) = &res_u32_never; - //[normal]~^ ERROR refutable + //[normal,min_exh_pats]~^ ERROR refutable let result_never: Result = x.result_never; match result_never {} //[normal]~^ ERROR non-exhaustive match result_never { - _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern + _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } match result_never { //[normal]~^ ERROR non-exhaustive - Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + Ok(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } match result_never { - Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern - _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern + Ok(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern + _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } match result_never { - Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern - Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + Ok(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern + Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } } @@ -145,11 +148,11 @@ fn void_same_as_never(x: NeverBundle) { } match opt_void { None => {} - Some(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + Some(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } match opt_void { None => {} - _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern + _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } let ref_void: &Void = &x.void; @@ -159,7 +162,7 @@ fn void_same_as_never(x: NeverBundle) { } let ref_opt_void: &Option = &None; match *ref_opt_void { - //[normal]~^ ERROR non-exhaustive + //[normal,min_exh_pats]~^ ERROR non-exhaustive None => {} } match *ref_opt_void { @@ -284,11 +287,11 @@ fn nested_validity_tracking(bundle: NeverBundle) { _ => {} //~ ERROR unreachable pattern } match tuple_never { - (_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + (_, _) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } match result_never { - Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern - Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + Ok(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern + Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } // These should be considered !known_valid and not warn unreachable. @@ -309,13 +312,13 @@ fn invalid_empty_match(bundle: NeverBundle) { match *x {} let x: &(u32, !) = &bundle.tuple_half_never; - match *x {} //[normal]~ ERROR non-exhaustive + match *x {} //[normal,min_exh_pats]~ ERROR non-exhaustive let x: &(!, !) = &bundle.tuple_never; - match *x {} //[normal]~ ERROR non-exhaustive + match *x {} //[normal,min_exh_pats]~ ERROR non-exhaustive let x: &Result = &bundle.result_never; - match *x {} //[normal]~ ERROR non-exhaustive + match *x {} //[normal,min_exh_pats]~ ERROR non-exhaustive let x: &[!; 3] = &bundle.array_3_never; - match *x {} //[normal]~ ERROR non-exhaustive + match *x {} //[normal,min_exh_pats]~ ERROR non-exhaustive } fn arrays_and_slices(x: NeverBundle) { @@ -323,7 +326,7 @@ fn arrays_and_slices(x: NeverBundle) { match slice_never {} //~^ ERROR non-empty match slice_never { - //[normal]~^ ERROR not covered + //[normal,min_exh_pats]~^ ERROR not covered [] => {} } match slice_never { @@ -332,7 +335,7 @@ fn arrays_and_slices(x: NeverBundle) { [_, _, ..] => {} } match slice_never { - //[normal]~^ ERROR `&[]`, `&[_]` and `&[_, _]` not covered + //[normal,min_exh_pats]~^ ERROR `&[]`, `&[_]` and `&[_, _]` not covered //[exhaustive_patterns]~^^ ERROR `&[]` not covered [_, _, _, ..] => {} } @@ -345,7 +348,7 @@ fn arrays_and_slices(x: NeverBundle) { _x => {} } match slice_never { - //[normal]~^ ERROR `&[]` and `&[_, ..]` not covered + //[normal,min_exh_pats]~^ ERROR `&[]` and `&[_, ..]` not covered //[exhaustive_patterns]~^^ ERROR `&[]` not covered &[..] if false => {} } @@ -360,13 +363,13 @@ fn arrays_and_slices(x: NeverBundle) { match array_3_never {} //[normal]~^ ERROR non-empty match array_3_never { - _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern + _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } match array_3_never { - [_, _, _] => {} //[exhaustive_patterns]~ ERROR unreachable pattern + [_, _, _] => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } match array_3_never { - [_, ..] => {} //[exhaustive_patterns]~ ERROR unreachable pattern + [_, ..] => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } let ref_array_3_never: &[!; 3] = &array_3_never; @@ -408,22 +411,22 @@ fn bindings(x: NeverBundle) { match opt_never { None => {} // !useful, !reachable - Some(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + Some(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } match opt_never { None => {} // !useful, !reachable - Some(_a) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + Some(_a) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } match opt_never { None => {} // !useful, !reachable - _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern + _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } match opt_never { None => {} // !useful, !reachable - _a => {} //[exhaustive_patterns]~ ERROR unreachable pattern + _a => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern } // The scrutinee is known_valid, but under the `&` isn't anymore. @@ -444,7 +447,7 @@ fn bindings(x: NeverBundle) { &_a => {} } match ref_opt_never { - //[normal]~^ ERROR non-exhaustive + //[normal,min_exh_pats]~^ ERROR non-exhaustive &None => {} } match ref_opt_never { @@ -485,7 +488,7 @@ fn bindings(x: NeverBundle) { ref _a => {} } match *ref_opt_never { - //[normal]~^ ERROR non-exhaustive + //[normal,min_exh_pats]~^ ERROR non-exhaustive None => {} } match *ref_opt_never { @@ -533,7 +536,7 @@ fn bindings(x: NeverBundle) { let ref_res_never: &Result = &x.result_never; match *ref_res_never { - //[normal]~^ ERROR non-exhaustive + //[normal,min_exh_pats]~^ ERROR non-exhaustive // useful, reachable Ok(_) => {} } @@ -544,7 +547,7 @@ fn bindings(x: NeverBundle) { _ => {} } match *ref_res_never { - //[normal]~^ ERROR non-exhaustive + //[normal,min_exh_pats]~^ ERROR non-exhaustive // useful, !reachable Ok(_a) => {} } @@ -563,7 +566,7 @@ fn bindings(x: NeverBundle) { let ref_tuple_half_never: &(u32, !) = &x.tuple_half_never; match *ref_tuple_half_never {} - //[normal]~^ ERROR non-empty + //[normal,min_exh_pats]~^ ERROR non-empty match *ref_tuple_half_never { // useful, reachable (_, _) => {} @@ -614,6 +617,7 @@ fn guards_and_validity(x: NeverBundle) { // useful, reachable _ => {} } + // Now the madness commences. The guard caused a load of the value thus asserting validity. So // there's no invalid value for `_` to catch. So the second pattern is unreachable despite the // guard not being taken. @@ -629,7 +633,7 @@ fn guards_and_validity(x: NeverBundle) { _a if false => {} } match ref_never { - //[normal]~^ ERROR non-exhaustive + //[normal,min_exh_pats]~^ ERROR non-exhaustive // useful, !reachable &_a if false => {} } @@ -657,7 +661,7 @@ fn diagnostics_subtlety(x: NeverBundle) { // Regression test for diagnostics: don't report `Some(Ok(_))` and `Some(Err(_))`. let x: &Option> = &None; match *x { - //[normal]~^ ERROR `Some(_)` not covered + //[normal,min_exh_pats]~^ ERROR `Some(_)` not covered None => {} } } From 8866449c6672f3fc7887edb96616a46530e18947 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 19 Jan 2024 09:44:03 +0100 Subject: [PATCH 08/10] Split assembly tests for ELF and MachO On ELF, the text section is opened with ".text", on MachO with ".section __TEXT,__text". Previously, on ELF this test was actually matching a GNU note section, which is no longer emitted on Solaris starting with LLVM 18. Fixes https://github.com/rust-lang/rust/issues/120105. --- tests/assembly/targets/targets-elf.rs | 65 +------------------- tests/assembly/targets/targets-macho.rs | 81 +++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 64 deletions(-) create mode 100644 tests/assembly/targets/targets-macho.rs diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index f6f2f5e88ffc3..dee0fa9f4a410 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -1,29 +1,5 @@ // assembly-output: emit-asm // ignore-tidy-linelength -// revisions: aarch64_apple_darwin -// [aarch64_apple_darwin] compile-flags: --target aarch64-apple-darwin -// [aarch64_apple_darwin] needs-llvm-components: aarch64 -// revisions: aarch64_apple_ios -// [aarch64_apple_ios] compile-flags: --target aarch64-apple-ios -// [aarch64_apple_ios] needs-llvm-components: aarch64 -// revisions: aarch64_apple_ios_macabi -// [aarch64_apple_ios_macabi] compile-flags: --target aarch64-apple-ios-macabi -// [aarch64_apple_ios_macabi] needs-llvm-components: aarch64 -// revisions: aarch64_apple_ios_sim -// [aarch64_apple_ios_sim] compile-flags: --target aarch64-apple-ios-sim -// [aarch64_apple_ios_sim] needs-llvm-components: aarch64 -// revisions: aarch64_apple_tvos -// [aarch64_apple_tvos] compile-flags: --target aarch64-apple-tvos -// [aarch64_apple_tvos] needs-llvm-components: aarch64 -// revisions: aarch64_apple_tvos_sim -// [aarch64_apple_tvos_sim] compile-flags: --target aarch64-apple-tvos-sim -// [aarch64_apple_tvos_sim] needs-llvm-components: aarch64 -// revisions: aarch64_apple_watchos -// [aarch64_apple_watchos] compile-flags: --target aarch64-apple-watchos -// [aarch64_apple_watchos] needs-llvm-components: aarch64 -// revisions: aarch64_apple_watchos_sim -// [aarch64_apple_watchos_sim] compile-flags: --target aarch64-apple-watchos-sim -// [aarch64_apple_watchos_sim] needs-llvm-components: aarch64 // revisions: aarch64_be_unknown_linux_gnu // [aarch64_be_unknown_linux_gnu] compile-flags: --target aarch64_be-unknown-linux-gnu // [aarch64_be_unknown_linux_gnu] needs-llvm-components: aarch64 @@ -93,15 +69,6 @@ // revisions: aarch64_wrs_vxworks // [aarch64_wrs_vxworks] compile-flags: --target aarch64-wrs-vxworks // [aarch64_wrs_vxworks] needs-llvm-components: aarch64 -// revisions: arm64_32_apple_watchos -// [arm64_32_apple_watchos] compile-flags: --target arm64_32-apple-watchos -// [arm64_32_apple_watchos] needs-llvm-components: aarch64 -// revisions: arm64e_apple_darwin -// [arm64e_apple_darwin] compile-flags: --target arm64e-apple-darwin -// [arm64e_apple_darwin] needs-llvm-components: aarch64 -// revisions: arm64e_apple_ios -// [arm64e_apple_ios] compile-flags: --target arm64e-apple-ios -// [arm64e_apple_ios] needs-llvm-components: aarch64 // revisions: arm_linux_androideabi // [arm_linux_androideabi] compile-flags: --target arm-linux-androideabi // [arm_linux_androideabi] needs-llvm-components: arm @@ -201,18 +168,12 @@ // revisions: armv7a_none_eabihf // [armv7a_none_eabihf] compile-flags: --target armv7a-none-eabihf // [armv7a_none_eabihf] needs-llvm-components: arm -// revisions: armv7k_apple_watchos -// [armv7k_apple_watchos] compile-flags: --target armv7k-apple-watchos -// [armv7k_apple_watchos] needs-llvm-components: arm // revisions: armv7r_none_eabi // [armv7r_none_eabi] compile-flags: --target armv7r-none-eabi // [armv7r_none_eabi] needs-llvm-components: arm // revisions: armv7r_none_eabihf // [armv7r_none_eabihf] compile-flags: --target armv7r-none-eabihf // [armv7r_none_eabihf] needs-llvm-components: arm -// revisions: armv7s_apple_ios -// [armv7s_apple_ios] compile-flags: --target armv7s-apple-ios -// [armv7s_apple_ios] needs-llvm-components: arm // FIXME: disabled since it fails on CI saying the csky component is missing /* revisions: csky_unknown_linux_gnuabiv2 @@ -228,9 +189,6 @@ // revisions: hexagon_unknown_none_elf // [hexagon_unknown_none_elf] compile-flags: --target hexagon-unknown-none-elf // [hexagon_unknown_none_elf] needs-llvm-components: hexagon -// revisions: i386_apple_ios -// [i386_apple_ios] compile-flags: --target i386-apple-ios -// [i386_apple_ios] needs-llvm-components: x86 // revisions: i586_pc_nto_qnx700 // [i586_pc_nto_qnx700] compile-flags: --target i586-pc-nto-qnx700 // [i586_pc_nto_qnx700] needs-llvm-components: x86 @@ -243,9 +201,6 @@ // revisions: i586_unknown_netbsd // [i586_unknown_netbsd] compile-flags: --target i586-unknown-netbsd // [i586_unknown_netbsd] needs-llvm-components: x86 -// revisions: i686_apple_darwin -// [i686_apple_darwin] compile-flags: --target i686-apple-darwin -// [i686_apple_darwin] needs-llvm-components: x86 // revisions: i686_linux_android // [i686_linux_android] compile-flags: --target i686-linux-android // [i686_linux_android] needs-llvm-components: x86 @@ -537,21 +492,6 @@ // revisions: wasm32_wasi_preview2 // [wasm32_wasi_preview2] compile-flags: --target wasm32-wasi-preview2 // [wasm32_wasi_preview2] needs-llvm-components: webassembly -// revisions: x86_64_apple_darwin -// [x86_64_apple_darwin] compile-flags: --target x86_64-apple-darwin -// [x86_64_apple_darwin] needs-llvm-components: x86 -// revisions: x86_64_apple_ios -// [x86_64_apple_ios] compile-flags: --target x86_64-apple-ios -// [x86_64_apple_ios] needs-llvm-components: x86 -// revisions: x86_64_apple_ios_macabi -// [x86_64_apple_ios_macabi] compile-flags: --target x86_64-apple-ios-macabi -// [x86_64_apple_ios_macabi] needs-llvm-components: x86 -// revisions: x86_64_apple_tvos -// [x86_64_apple_tvos] compile-flags: --target x86_64-apple-tvos -// [x86_64_apple_tvos] needs-llvm-components: x86 -// revisions: x86_64_apple_watchos_sim -// [x86_64_apple_watchos_sim] compile-flags: --target x86_64-apple-watchos-sim -// [x86_64_apple_watchos_sim] needs-llvm-components: x86 // revisions: x86_64_fortanix_unknown_sgx // [x86_64_fortanix_unknown_sgx] compile-flags: --target x86_64-fortanix-unknown-sgx // [x86_64_fortanix_unknown_sgx] needs-llvm-components: x86 @@ -618,9 +558,6 @@ // revisions: x86_64_wrs_vxworks // [x86_64_wrs_vxworks] compile-flags: --target x86_64-wrs-vxworks // [x86_64_wrs_vxworks] needs-llvm-components: x86 -// revisions: x86_64h_apple_darwin -// [x86_64h_apple_darwin] compile-flags: --target x86_64h-apple-darwin -// [x86_64h_apple_darwin] needs-llvm-components: x86 // Sanity-check that each target can produce assembly code. @@ -636,4 +573,4 @@ pub fn test() -> u8 { 42 } -// CHECK: .section +// CHECK: .text diff --git a/tests/assembly/targets/targets-macho.rs b/tests/assembly/targets/targets-macho.rs new file mode 100644 index 0000000000000..ead9ccfc8e74e --- /dev/null +++ b/tests/assembly/targets/targets-macho.rs @@ -0,0 +1,81 @@ +// assembly-output: emit-asm +// ignore-tidy-linelength +// revisions: aarch64_apple_darwin +// [aarch64_apple_darwin] compile-flags: --target aarch64-apple-darwin +// [aarch64_apple_darwin] needs-llvm-components: aarch64 +// revisions: aarch64_apple_ios +// [aarch64_apple_ios] compile-flags: --target aarch64-apple-ios +// [aarch64_apple_ios] needs-llvm-components: aarch64 +// revisions: aarch64_apple_ios_macabi +// [aarch64_apple_ios_macabi] compile-flags: --target aarch64-apple-ios-macabi +// [aarch64_apple_ios_macabi] needs-llvm-components: aarch64 +// revisions: aarch64_apple_ios_sim +// [aarch64_apple_ios_sim] compile-flags: --target aarch64-apple-ios-sim +// [aarch64_apple_ios_sim] needs-llvm-components: aarch64 +// revisions: aarch64_apple_tvos +// [aarch64_apple_tvos] compile-flags: --target aarch64-apple-tvos +// [aarch64_apple_tvos] needs-llvm-components: aarch64 +// revisions: aarch64_apple_tvos_sim +// [aarch64_apple_tvos_sim] compile-flags: --target aarch64-apple-tvos-sim +// [aarch64_apple_tvos_sim] needs-llvm-components: aarch64 +// revisions: aarch64_apple_watchos +// [aarch64_apple_watchos] compile-flags: --target aarch64-apple-watchos +// [aarch64_apple_watchos] needs-llvm-components: aarch64 +// revisions: aarch64_apple_watchos_sim +// [aarch64_apple_watchos_sim] compile-flags: --target aarch64-apple-watchos-sim +// [aarch64_apple_watchos_sim] needs-llvm-components: aarch64 +// revisions: arm64_32_apple_watchos +// [arm64_32_apple_watchos] compile-flags: --target arm64_32-apple-watchos +// [arm64_32_apple_watchos] needs-llvm-components: aarch64 +// revisions: arm64e_apple_darwin +// [arm64e_apple_darwin] compile-flags: --target arm64e-apple-darwin +// [arm64e_apple_darwin] needs-llvm-components: aarch64 +// revisions: arm64e_apple_ios +// [arm64e_apple_ios] compile-flags: --target arm64e-apple-ios +// [arm64e_apple_ios] needs-llvm-components: aarch64 +// revisions: armv7k_apple_watchos +// [armv7k_apple_watchos] compile-flags: --target armv7k-apple-watchos +// [armv7k_apple_watchos] needs-llvm-components: arm +// revisions: armv7s_apple_ios +// [armv7s_apple_ios] compile-flags: --target armv7s-apple-ios +// [armv7s_apple_ios] needs-llvm-components: arm +// revisions: i386_apple_ios +// [i386_apple_ios] compile-flags: --target i386-apple-ios +// [i386_apple_ios] needs-llvm-components: x86 +// revisions: i686_apple_darwin +// [i686_apple_darwin] compile-flags: --target i686-apple-darwin +// [i686_apple_darwin] needs-llvm-components: x86 +// revisions: x86_64_apple_darwin +// [x86_64_apple_darwin] compile-flags: --target x86_64-apple-darwin +// [x86_64_apple_darwin] needs-llvm-components: x86 +// revisions: x86_64_apple_ios +// [x86_64_apple_ios] compile-flags: --target x86_64-apple-ios +// [x86_64_apple_ios] needs-llvm-components: x86 +// revisions: x86_64_apple_ios_macabi +// [x86_64_apple_ios_macabi] compile-flags: --target x86_64-apple-ios-macabi +// [x86_64_apple_ios_macabi] needs-llvm-components: x86 +// revisions: x86_64_apple_tvos +// [x86_64_apple_tvos] compile-flags: --target x86_64-apple-tvos +// [x86_64_apple_tvos] needs-llvm-components: x86 +// revisions: x86_64_apple_watchos_sim +// [x86_64_apple_watchos_sim] compile-flags: --target x86_64-apple-watchos-sim +// [x86_64_apple_watchos_sim] needs-llvm-components: x86 +// revisions: x86_64h_apple_darwin +// [x86_64h_apple_darwin] compile-flags: --target x86_64h-apple-darwin +// [x86_64h_apple_darwin] needs-llvm-components: x86 + +// Sanity-check that each target can produce assembly code. + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +#[lang = "sized"] +trait Sized {} + +pub fn test() -> u8 { + 42 +} + +// CHECK: .section __TEXT,__text From 27717dbd4d0df888e66661690199d5dd07078259 Mon Sep 17 00:00:00 2001 From: Andrew Zhogin Date: Mon, 22 Jan 2024 00:58:50 +0700 Subject: [PATCH 09/10] Builtin macros effectively have implicit #[collapse_debuginfo(yes)] attribute --- compiler/rustc_expand/src/base.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 29b70f33a6c7d..657e19277a7ed 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -796,9 +796,15 @@ impl SyntaxExtension { /// | external | no | if-ext | if-ext | yes | /// | yes | yes | yes | yes | yes | fn get_collapse_debuginfo(sess: &Session, attrs: &[ast::Attribute], is_local: bool) -> bool { - let collapse_debuginfo_attr = attr::find_by_name(attrs, sym::collapse_debuginfo) + let mut collapse_debuginfo_attr = attr::find_by_name(attrs, sym::collapse_debuginfo) .map(|v| Self::collapse_debuginfo_by_name(sess, v)) .unwrap_or(CollapseMacroDebuginfo::Unspecified); + if collapse_debuginfo_attr == CollapseMacroDebuginfo::Unspecified + && attr::contains_name(attrs, sym::rustc_builtin_macro) + { + collapse_debuginfo_attr = CollapseMacroDebuginfo::Yes; + } + let flag = sess.opts.unstable_opts.collapse_macro_debuginfo; let attr = collapse_debuginfo_attr; let ext = !is_local; From f94a94227cad840e45b11f5a537748b626737c6c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 25 Jan 2024 18:11:54 -0800 Subject: [PATCH 10/10] Export core::str::from_raw_parts{,_mut} into alloc::str and std::str --- library/alloc/src/str.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index 38f9f39fbf89a..ade114678b7f9 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -30,6 +30,8 @@ pub use core::str::SplitAsciiWhitespace; pub use core::str::SplitInclusive; #[stable(feature = "rust1", since = "1.0.0")] pub use core::str::SplitWhitespace; +#[unstable(feature = "str_from_raw_parts", issue = "119206")] +pub use core::str::{from_raw_parts, from_raw_parts_mut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::str::{from_utf8, from_utf8_mut, Bytes, CharIndices, Chars}; #[stable(feature = "rust1", since = "1.0.0")]