diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 0cf73178d679d..8f0b12cb4feef 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -64,8 +64,8 @@ struct AstValidator<'a> { /// certain positions. is_assoc_ty_bound_banned: bool, - /// Used to allow `let` expressions in certain syntactic locations. - is_let_allowed: bool, + /// See [ForbiddenLetReason] + forbidden_let_reason: Option, lint_buffer: &'a mut LintBuffer, } @@ -103,20 +103,28 @@ impl<'a> AstValidator<'a> { self.is_tilde_const_allowed = old; } - fn with_let_allowed(&mut self, allowed: bool, f: impl FnOnce(&mut Self, bool)) { - let old = mem::replace(&mut self.is_let_allowed, allowed); + fn with_let_management( + &mut self, + forbidden_let_reason: Option, + f: impl FnOnce(&mut Self, Option), + ) { + let old = mem::replace(&mut self.forbidden_let_reason, forbidden_let_reason); f(self, old); - self.is_let_allowed = old; + self.forbidden_let_reason = old; } /// Emits an error banning the `let` expression provided in the given location. - fn ban_let_expr(&self, expr: &'a Expr) { + fn ban_let_expr(&self, expr: &'a Expr, forbidden_let_reason: ForbiddenLetReason) { let sess = &self.session; if sess.opts.unstable_features.is_nightly_build() { - sess.struct_span_err(expr.span, "`let` expressions are not supported here") - .note("only supported directly in conditions of `if`- and `while`-expressions") - .note("as well as when nested within `&&` and parentheses in those conditions") - .emit(); + let err = "`let` expressions are not supported here"; + let mut diag = sess.struct_span_err(expr.span, err); + diag.note("only supported directly in conditions of `if` and `while` expressions"); + diag.note("as well as when nested within `&&` and parentheses in those conditions"); + if let ForbiddenLetReason::ForbiddenWithOr(span) = forbidden_let_reason { + diag.span_note(span, "`||` operators are not allowed in let chain expressions"); + } + diag.emit(); } else { sess.struct_span_err(expr.span, "expected expression, found statement (`let`)") .note("variable declaration using `let` is a statement") @@ -988,39 +996,48 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_expr(&mut self, expr: &'a Expr) { - self.with_let_allowed(false, |this, let_allowed| match &expr.kind { - ExprKind::If(cond, then, opt_else) => { - this.visit_block(then); - walk_list!(this, visit_expr, opt_else); - this.with_let_allowed(true, |this, _| this.visit_expr(cond)); - return; - } - ExprKind::Let(..) if !let_allowed => this.ban_let_expr(expr), - ExprKind::Match(expr, arms) => { - this.visit_expr(expr); - for arm in arms { - this.visit_expr(&arm.body); - this.visit_pat(&arm.pat); - walk_list!(this, visit_attribute, &arm.attrs); - if let Some(ref guard) = arm.guard { - if let ExprKind::Let(_, ref expr, _) = guard.kind { - this.with_let_allowed(true, |this, _| this.visit_expr(expr)); + self.with_let_management(Some(ForbiddenLetReason::GenericForbidden), |this, forbidden_let_reason| { + match &expr.kind { + ExprKind::Binary(Spanned { node: BinOpKind::Or, span }, lhs, rhs) => { + let forbidden_let_reason = Some(ForbiddenLetReason::ForbiddenWithOr(*span)); + this.with_let_management(forbidden_let_reason, |this, _| this.visit_expr(lhs)); + this.with_let_management(forbidden_let_reason, |this, _| this.visit_expr(rhs)); + } + ExprKind::If(cond, then, opt_else) => { + this.visit_block(then); + walk_list!(this, visit_expr, opt_else); + this.with_let_management(None, |this, _| this.visit_expr(cond)); + return; + } + ExprKind::Let(..) if let Some(elem) = forbidden_let_reason => { + this.ban_let_expr(expr, elem); + }, + ExprKind::Match(scrutinee, arms) => { + this.visit_expr(scrutinee); + for arm in arms { + this.visit_expr(&arm.body); + this.visit_pat(&arm.pat); + walk_list!(this, visit_attribute, &arm.attrs); + if let Some(guard) = &arm.guard && let ExprKind::Let(_, guard_expr, _) = &guard.kind { + this.with_let_management(None, |this, _| { + this.visit_expr(guard_expr) + }); return; } } } + ExprKind::Paren(_) | ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, ..) => { + this.with_let_management(forbidden_let_reason, |this, _| visit::walk_expr(this, expr)); + return; + } + ExprKind::While(cond, then, opt_label) => { + walk_list!(this, visit_label, opt_label); + this.visit_block(then); + this.with_let_management(None, |this, _| this.visit_expr(cond)); + return; + } + _ => visit::walk_expr(this, expr), } - ExprKind::Paren(_) | ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, ..) => { - this.with_let_allowed(let_allowed, |this, _| visit::walk_expr(this, expr)); - return; - } - ExprKind::While(cond, then, opt_label) => { - walk_list!(this, visit_label, opt_label); - this.visit_block(then); - this.with_let_allowed(true, |this, _| this.visit_expr(cond)); - return; - } - _ => visit::walk_expr(this, expr), }); } @@ -1772,10 +1789,19 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> is_tilde_const_allowed: false, is_impl_trait_banned: false, is_assoc_ty_bound_banned: false, - is_let_allowed: false, + forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden), lint_buffer: lints, }; visit::walk_crate(&mut validator, krate); validator.has_proc_macro_decls } + +/// Used to forbid `let` expressions in certain syntactic locations. +#[derive(Clone, Copy)] +enum ForbiddenLetReason { + /// A let chain with the `||` operator + ForbiddenWithOr(Span), + /// `let` is not valid and the source environment is not important + GenericForbidden, +} diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 876dd7f757c5a..9d52c32885db0 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -4,11 +4,13 @@ //! //! The crate also contains other misc AST visitors, e.g. `node_count` and `show_span`. -#![feature(iter_is_partitioned)] +#![allow(rustc::potential_query_instability)] #![feature(box_patterns)] +#![feature(if_let_guard)] +#![feature(iter_is_partitioned)] +#![feature(let_chains)] #![feature(let_else)] #![recursion_limit = "256"] -#![allow(rustc::potential_query_instability)] pub mod ast_validation; pub mod feature_gate; diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index b80d2e52ee709..c94da838680e0 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -7,7 +7,8 @@ use super::{PatCtxt, PatternError}; use rustc_arena::TypedArena; use rustc_ast::Mutability; use rustc_errors::{ - error_code, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + error_code, pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, + ErrorGuaranteed, }; use rustc_hir as hir; use rustc_hir::def::*; @@ -20,7 +21,7 @@ use rustc_session::lint::builtin::{ }; use rustc_session::Session; use rustc_span::source_map::Spanned; -use rustc_span::{DesugaringKind, ExpnKind, MultiSpan, Span}; +use rustc_span::{BytePos, DesugaringKind, ExpnKind, MultiSpan, Span}; crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) { let body_id = match def_id.as_local() { @@ -241,6 +242,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } let joined_patterns = joined_uncovered_patterns(&cx, &witnesses); + + let mut bindings = vec![]; + let mut err = struct_span_err!( self.tcx.sess, pat.span, @@ -257,6 +261,16 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { false } _ => { + pat.walk(&mut |pat: &hir::Pat<'_>| { + match pat.kind { + hir::PatKind::Binding(_, _, ident, _) => { + bindings.push(ident); + } + _ => {} + } + true + }); + err.span_label(pat.span, pattern_not_covered_label(&witnesses, &joined_patterns)); true } @@ -267,13 +281,71 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { "`let` bindings require an \"irrefutable pattern\", like a `struct` or \ an `enum` with only one variant", ); - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - err.span_suggestion( - span, - "you might want to use `if let` to ignore the variant that isn't matched", - format!("if {} {{ /* */ }}", &snippet[..snippet.len() - 1]), + if self.tcx.sess.source_map().span_to_snippet(span).is_ok() { + let semi_span = span.shrink_to_hi().with_lo(span.hi() - BytePos(1)); + let start_span = span.shrink_to_lo(); + let end_span = semi_span.shrink_to_lo(); + err.multipart_suggestion( + &format!( + "you might want to use `if let` to ignore the variant{} that {} matched", + pluralize!(witnesses.len()), + match witnesses.len() { + 1 => "isn't", + _ => "aren't", + }, + ), + vec![ + match &bindings[..] { + [] => (start_span, "if ".to_string()), + [binding] => (start_span, format!("let {} = if ", binding)), + bindings => ( + start_span, + format!( + "let ({}) = if ", + bindings + .iter() + .map(|ident| ident.to_string()) + .collect::>() + .join(", ") + ), + ), + }, + match &bindings[..] { + [] => (semi_span, " { todo!() }".to_string()), + [binding] => { + (end_span, format!(" {{ {} }} else {{ todo!() }}", binding)) + } + bindings => ( + end_span, + format!( + " {{ ({}) }} else {{ todo!() }}", + bindings + .iter() + .map(|ident| ident.to_string()) + .collect::>() + .join(", ") + ), + ), + }, + ], Applicability::HasPlaceholders, ); + if !bindings.is_empty() && cx.tcx.sess.is_nightly_build() { + err.span_suggestion_verbose( + semi_span.shrink_to_lo(), + &format!( + "alternatively, on nightly, you might want to use \ + `#![feature(let_else)]` to handle the variant{} that {} matched", + pluralize!(witnesses.len()), + match witnesses.len() { + 1 => "isn't", + _ => "aren't", + }, + ), + " else { todo!() }".to_string(), + Applicability::HasPlaceholders, + ); + } } err.note( "for more information, visit \ diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 221dc86c1d46d..1d36ff059de81 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1072,6 +1072,7 @@ impl CrateCheckConfig { // NOTE: This should be kept in sync with `default_configuration` and // `fill_well_known_values` const WELL_KNOWN_NAMES: &[Symbol] = &[ + // rustc sym::unix, sym::windows, sym::target_os, @@ -1091,9 +1092,12 @@ impl CrateCheckConfig { sym::debug_assertions, sym::proc_macro, sym::test, + sym::feature, + // rustdoc sym::doc, sym::doctest, - sym::feature, + // miri + sym::miri, ]; // We only insert well-known names if `names()` was activated @@ -1128,13 +1132,14 @@ impl CrateCheckConfig { // No-values for name in [ + sym::doc, + sym::miri, sym::unix, - sym::windows, - sym::debug_assertions, - sym::proc_macro, sym::test, - sym::doc, sym::doctest, + sym::windows, + sym::proc_macro, + sym::debug_assertions, sym::target_thread_local, ] { self.values_valid.entry(name).or_default(); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3f44292e03425..3884578f5d46c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -891,6 +891,7 @@ symbols! { minnumf32, minnumf64, mips_target_feature, + miri, misc, mmx_reg, modifiers, diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 6f9579043c37d..1912694412b98 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -127,7 +127,11 @@ pub trait Clone: Sized { /// allocations. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn clone_from(&mut self, source: &Self) { + #[default_method_body_is_const] + fn clone_from(&mut self, source: &Self) + where + Self: ~const Drop, + { *self = source.clone() } } @@ -178,7 +182,8 @@ mod impls { ($($t:ty)*) => { $( #[stable(feature = "rust1", since = "1.0.0")] - impl Clone for $t { + #[rustc_const_unstable(feature = "const_clone", issue = "91805")] + impl const Clone for $t { #[inline] fn clone(&self) -> Self { *self @@ -196,7 +201,8 @@ mod impls { } #[unstable(feature = "never_type", issue = "35121")] - impl Clone for ! { + #[rustc_const_unstable(feature = "const_clone", issue = "91805")] + impl const Clone for ! { #[inline] fn clone(&self) -> Self { *self @@ -204,7 +210,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl Clone for *const T { + #[rustc_const_unstable(feature = "const_clone", issue = "91805")] + impl const Clone for *const T { #[inline] fn clone(&self) -> Self { *self @@ -212,7 +219,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl Clone for *mut T { + #[rustc_const_unstable(feature = "const_clone", issue = "91805")] + impl const Clone for *mut T { #[inline] fn clone(&self) -> Self { *self @@ -221,7 +229,8 @@ mod impls { /// Shared references can be cloned, but mutable references *cannot*! #[stable(feature = "rust1", since = "1.0.0")] - impl Clone for &T { + #[rustc_const_unstable(feature = "const_clone", issue = "91805")] + impl const Clone for &T { #[inline] #[rustc_diagnostic_item = "noop_method_clone"] fn clone(&self) -> Self { diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 0ceedf936333d..f5ea5f5ba50c0 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -300,7 +300,8 @@ pub trait Into: Sized { /// that encapsulate multiple error types. See the "Examples" section and [the book][book] for more /// details. /// -/// **Note: This trait must not fail**. If the conversion can fail, use [`TryFrom`]. +/// **Note: This trait must not fail**. The `From` trait is intended for perfect conversions. +/// If the conversion can fail or is not perfect, use [`TryFrom`]. /// /// # Generic Implementations /// @@ -690,7 +691,8 @@ impl AsMut for str { pub enum Infallible {} #[stable(feature = "convert_infallible", since = "1.34.0")] -impl Clone for Infallible { +#[rustc_const_unstable(feature = "const_clone", issue = "91805")] +impl const Clone for Infallible { fn clone(&self) -> Infallible { match *self {} } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index f5c0a3b5cd849..b38df1c2d0228 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1859,6 +1859,77 @@ pub trait Iterator { try_process(self, |i| i.collect()) } + /// Collects all the items from an iterator into a collection. + /// + /// This method consumes the iterator and adds all its items to the + /// passed collection. The collection is then returned, so the call chain + /// can be continued. + /// + /// This is useful when you already have a collection and wants to add + /// the iterator items to it. + /// + /// This method is a convenience method to call [Extend::extend](trait.Extend.html), + /// but instead of being called on a collection, it's called on an iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_collect_into)] + /// + /// let a = [1, 2, 3]; + /// let mut vec: Vec:: = vec![0, 1]; + /// + /// a.iter().map(|&x| x * 2).collect_into(&mut vec); + /// a.iter().map(|&x| x * 10).collect_into(&mut vec); + /// + /// assert_eq!(vec![0, 1, 2, 4, 6, 10, 20, 30], vec); + /// ``` + /// + /// `Vec` can have a manual set capacity to avoid reallocating it: + /// + /// ``` + /// #![feature(iter_collect_into)] + /// + /// let a = [1, 2, 3]; + /// let mut vec: Vec:: = Vec::with_capacity(6); + /// + /// a.iter().map(|&x| x * 2).collect_into(&mut vec); + /// a.iter().map(|&x| x * 10).collect_into(&mut vec); + /// + /// assert_eq!(6, vec.capacity()); + /// println!("{:?}", vec); + /// ``` + /// + /// The returned mutable reference can be used to continue the call chain: + /// + /// ``` + /// #![feature(iter_collect_into)] + /// + /// let a = [1, 2, 3]; + /// let mut vec: Vec:: = Vec::with_capacity(6); + /// + /// let count = a.iter().collect_into(&mut vec).iter().count(); + /// + /// assert_eq!(count, vec.len()); + /// println!("Vec len is {}", count); + /// + /// let count = a.iter().collect_into(&mut vec).iter().count(); + /// + /// assert_eq!(count, vec.len()); + /// println!("Vec len now is {}", count); + /// ``` + #[inline] + #[unstable(feature = "iter_collect_into", reason = "new API", issue = "94780")] + fn collect_into>(self, collection: &mut E) -> &mut E + where + Self: Sized, + { + collection.extend(self); + collection + } + /// Consumes an iterator, creating two collections from it. /// /// The predicate passed to `partition()` can return `true`, or `false`. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index f436afbee448e..ddd8ae0c02ca5 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -104,6 +104,7 @@ #![feature(const_caller_location)] #![feature(const_cell_into_inner)] #![feature(const_char_convert)] +#![feature(const_clone)] #![feature(const_discriminant)] #![feature(const_eval_select)] #![feature(const_float_bits_conv)] diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 508837f63c3be..a6286f8d8d103 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1857,7 +1857,11 @@ const fn expect_failed(msg: &str) -> ! { ///////////////////////////////////////////////////////////////////////////// #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Option { +#[rustc_const_unstable(feature = "const_clone", issue = "91805")] +impl const Clone for Option +where + T: ~const Clone + ~const Drop, +{ #[inline] fn clone(&self) -> Self { match self { diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 0aa8e9960a8dd..77b93e0c24cc9 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -642,7 +642,8 @@ impl NonNull<[T]> { } #[stable(feature = "nonnull", since = "1.25.0")] -impl Clone for NonNull { +#[rustc_const_unstable(feature = "const_clone", issue = "91805")] +impl const Clone for NonNull { #[inline] fn clone(&self) -> Self { *self diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index 661d111c99d52..cff68f64f78e0 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -146,7 +146,8 @@ impl Unique { } #[unstable(feature = "ptr_internals", issue = "none")] -impl Clone for Unique { +#[rustc_const_unstable(feature = "const_clone", issue = "91805")] +impl const Clone for Unique { #[inline] fn clone(&self) -> Self { *self diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 1827860a39045..5a189f2b09811 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1801,7 +1801,12 @@ fn unwrap_failed(_msg: &str, _error: &T) -> ! { ///////////////////////////////////////////////////////////////////////////// #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Result { +#[rustc_const_unstable(feature = "const_clone", issue = "91805")] +impl const Clone for Result +where + T: ~const Clone + ~const Drop, + E: ~const Clone + ~const Drop, +{ #[inline] fn clone(&self) -> Self { match self { diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index cf69f0a7a4d7e..32bd68e3d2554 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -543,6 +543,14 @@ fn test_try_collect() { assert_eq!(v, Continue(vec![4, 5])); } +#[test] +fn test_collect_into() { + let a = vec![1, 2, 3, 4, 5]; + let mut b = Vec::new(); + a.iter().cloned().collect_into(&mut b); + assert!(a == b); +} + // just tests by whether or not this compiles fn _empty_impl_all_auto_traits() { use std::panic::{RefUnwindSafe, UnwindSafe}; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 2437f4afdeb5e..dc3740228274b 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -62,6 +62,7 @@ #![feature(slice_partition_dedup)] #![feature(int_log)] #![feature(iter_advance_by)] +#![feature(iter_collect_into)] #![feature(iter_partition_in_place)] #![feature(iter_intersperse)] #![feature(iter_is_partitioned)] diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs index 959fe6943f6ee..4d5cf658def0d 100644 --- a/library/std/src/net/tcp/tests.rs +++ b/library/std/src/net/tcp/tests.rs @@ -508,6 +508,7 @@ fn close_readwrite_smoke() { } #[test] +#[cfg_attr(target_env = "sgx", ignore)] fn close_read_wakes_up() { each_ip(&mut |addr| { let a = t!(TcpListener::bind(&addr)); diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs index 4af58f1a38075..c4847b529a361 100644 --- a/library/std/src/thread/scoped.rs +++ b/library/std/src/thread/scoped.rs @@ -107,6 +107,24 @@ impl ScopeData { /// a.push(4); /// assert_eq!(x, a.len()); /// ``` +/// +/// # Lifetimes +/// +/// Scoped threads involve two lifetimes: `'scope` and `'env`. +/// +/// The `'scope` lifetime represents the lifetime of the scope itself. +/// That is: the time during which new scoped threads may be spawned, +/// and also the time during which they might still be running. +/// Once this lifetime ends, all scoped threads are joined. +/// This lifetime starts within the `scope` function, before `f` (the argument to `scope`) starts. +/// It ends after `f` returns and all scoped threads have been joined, but before `scope` returns. +/// +/// The `'env` lifetime represents the lifetime of whatever is borrowed by the scoped threads. +/// This lifetime must outlast the call to `scope`, and thus cannot be smaller than `'scope`. +/// It can be as small as the call to `scope`, meaning that anything that outlives this call, +/// such as local variables defined right before the scope, can be borrowed by the scoped threads. +/// +/// The `'env: 'scope` bound is part of the definition of the `Scope` type. #[track_caller] pub fn scope<'env, F, T>(f: F) -> T where diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 2ae63858ff610..2ee67d623eec9 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -193,7 +193,6 @@ const EXTRA_CHECK_CFGS: &[(Option, &'static str, Option<&[&'static str]>)] (None, "bootstrap", None), (Some(Mode::Rustc), "parallel_compiler", None), (Some(Mode::ToolRustc), "parallel_compiler", None), - (Some(Mode::Std), "miri", None), (Some(Mode::Std), "stdarch_intel_sde", None), (Some(Mode::Std), "no_fp_fmt_parse", None), (Some(Mode::Std), "no_global_oom_handling", None), diff --git a/src/test/ui/check-cfg/well-known-names.rs b/src/test/ui/check-cfg/well-known-names.rs index a66568a2ffdc9..e57fb69a1e05f 100644 --- a/src/test/ui/check-cfg/well-known-names.rs +++ b/src/test/ui/check-cfg/well-known-names.rs @@ -24,4 +24,10 @@ fn unix_misspell() {} #[cfg(unix)] fn unix() {} +#[cfg(miri)] +fn miri() {} + +#[cfg(doc)] +fn doc() {} + fn main() {} diff --git a/src/test/ui/check-cfg/well-known-values.rs b/src/test/ui/check-cfg/well-known-values.rs index 46004be43d812..96375dc8d3130 100644 --- a/src/test/ui/check-cfg/well-known-values.rs +++ b/src/test/ui/check-cfg/well-known-values.rs @@ -25,4 +25,18 @@ fn unix_with_value() {} #[cfg(unix)] fn unix() {} +#[cfg(miri = "miri")] +//~^ WARNING unexpected `cfg` condition value +fn miri_with_value() {} + +#[cfg(miri)] +fn miri() {} + +#[cfg(doc = "linux")] +//~^ WARNING unexpected `cfg` condition value +fn doc_with_value() {} + +#[cfg(doc)] +fn doc() {} + fn main() {} diff --git a/src/test/ui/check-cfg/well-known-values.stderr b/src/test/ui/check-cfg/well-known-values.stderr index 8eefd6aaf35ec..8b04c770fb505 100644 --- a/src/test/ui/check-cfg/well-known-values.stderr +++ b/src/test/ui/check-cfg/well-known-values.stderr @@ -29,5 +29,25 @@ LL | #[cfg(unix = "aa")] | = note: no expected value for `unix` -warning: 3 warnings emitted +warning: unexpected `cfg` condition value + --> $DIR/well-known-values.rs:28:7 + | +LL | #[cfg(miri = "miri")] + | ^^^^--------- + | | + | help: remove the value + | + = note: no expected value for `miri` + +warning: unexpected `cfg` condition value + --> $DIR/well-known-values.rs:35:7 + | +LL | #[cfg(doc = "linux")] + | ^^^---------- + | | + | help: remove the value + | + = note: no expected value for `doc` + +warning: 5 warnings emitted diff --git a/src/test/ui/consts/const-match-check.eval1.stderr b/src/test/ui/consts/const-match-check.eval1.stderr index 4141cc4ab1a48..6e61dbbd8eee3 100644 --- a/src/test/ui/consts/const-match-check.eval1.stderr +++ b/src/test/ui/consts/const-match-check.eval1.stderr @@ -7,10 +7,10 @@ LL | A = { let 0 = 0; 0 }, = 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 `i32` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | A = { if let 0 = 0 { /* */ } 0 }, - | ~~~~~~~~~~~~~~~~~~~~~~ +LL | A = { if let 0 = 0 { todo!() } 0 }, + | ++ ~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/consts/const-match-check.eval2.stderr b/src/test/ui/consts/const-match-check.eval2.stderr index af86ba0cc82f8..1b3b6e06c3df6 100644 --- a/src/test/ui/consts/const-match-check.eval2.stderr +++ b/src/test/ui/consts/const-match-check.eval2.stderr @@ -7,10 +7,10 @@ LL | let x: [i32; { let 0 = 0; 0 }] = []; = 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 `i32` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | let x: [i32; { if let 0 = 0 { /* */ } 0 }] = []; - | ~~~~~~~~~~~~~~~~~~~~~~ +LL | let x: [i32; { if let 0 = 0 { todo!() } 0 }] = []; + | ++ ~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/consts/const-match-check.matchck.stderr b/src/test/ui/consts/const-match-check.matchck.stderr index f71490eba6135..bc8edfa7af9f4 100644 --- a/src/test/ui/consts/const-match-check.matchck.stderr +++ b/src/test/ui/consts/const-match-check.matchck.stderr @@ -7,10 +7,10 @@ LL | const X: i32 = { let 0 = 0; 0 }; = 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 `i32` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | const X: i32 = { if let 0 = 0 { /* */ } 0 }; - | ~~~~~~~~~~~~~~~~~~~~~~ +LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; + | ++ ~~~~~~~~~~~ error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered --> $DIR/const-match-check.rs:8:23 @@ -21,10 +21,10 @@ LL | static Y: i32 = { let 0 = 0; 0 }; = 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 `i32` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | static Y: i32 = { if let 0 = 0 { /* */ } 0 }; - | ~~~~~~~~~~~~~~~~~~~~~~ +LL | static Y: i32 = { if let 0 = 0 { todo!() } 0 }; + | ++ ~~~~~~~~~~~ error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered --> $DIR/const-match-check.rs:13:26 @@ -35,10 +35,10 @@ LL | const X: i32 = { let 0 = 0; 0 }; = 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 `i32` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | const X: i32 = { if let 0 = 0 { /* */ } 0 }; - | ~~~~~~~~~~~~~~~~~~~~~~ +LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; + | ++ ~~~~~~~~~~~ error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered --> $DIR/const-match-check.rs:19:26 @@ -49,10 +49,10 @@ LL | const X: i32 = { let 0 = 0; 0 }; = 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 `i32` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | const X: i32 = { if let 0 = 0 { /* */ } 0 }; - | ~~~~~~~~~~~~~~~~~~~~~~ +LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; + | ++ ~~~~~~~~~~~ error: aborting due to 4 previous errors diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr index 8dd0f377533ce..909aa73a74a38 100644 --- a/src/test/ui/empty/empty-never-array.stderr +++ b/src/test/ui/empty/empty-never-array.stderr @@ -16,8 +16,12 @@ LL | T(T, [!; 0]), = note: the matched value is of type `Helper` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let Helper::U(u) = Helper::T(t, []) { /* */ } +LL | let u = if let Helper::U(u) = Helper::T(t, []) { u } else { todo!() }; + | ++++++++++ ++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched | +LL | let Helper::U(u) = Helper::T(t, []) else { todo!() }; + | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0005.stderr b/src/test/ui/error-codes/E0005.stderr index 208c625a53e95..55b1112b5f8ec 100644 --- a/src/test/ui/error-codes/E0005.stderr +++ b/src/test/ui/error-codes/E0005.stderr @@ -22,8 +22,12 @@ LL | | } = note: the matched value is of type `Option` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let Some(y) = x { /* */ } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | let y = if let Some(y) = x { y } else { todo!() }; + | ++++++++++ ++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched + | +LL | let Some(y) = x else { todo!() }; + | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr index c2ffda6bb72d2..21180f31bbd26 100644 --- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr +++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr @@ -21,8 +21,12 @@ LL | | } = note: the matched value is of type `Result` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let Ok(_x) = foo() { /* */ } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | let _x = if let Ok(_x) = foo() { _x } else { todo!() }; + | +++++++++++ +++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched + | +LL | let Ok(_x) = foo() else { todo!() }; + | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr index 37a35700b36d5..95b22ac059482 100644 --- a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr +++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr @@ -7,10 +7,10 @@ LL | let (0 | (1 | 2)) = 0; = 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 `i32` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | if let (0 | (1 | 2)) = 0 { /* */ } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | if let (0 | (1 | 2)) = 0 { todo!() } + | ++ ~~~~~~~~~~~ error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:3:11 diff --git a/src/test/ui/pattern/usefulness/issue-31561.stderr b/src/test/ui/pattern/usefulness/issue-31561.stderr index dffcfc016072f..9da6b5eeead23 100644 --- a/src/test/ui/pattern/usefulness/issue-31561.stderr +++ b/src/test/ui/pattern/usefulness/issue-31561.stderr @@ -17,10 +17,14 @@ LL | Bar, LL | Baz | ^^^ not covered = note: the matched value is of type `Thing` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | if let Thing::Foo(y) = Thing::Foo(1) { /* */ } +LL | let y = if let Thing::Foo(y) = Thing::Foo(1) { y } else { todo!() }; + | ++++++++++ ++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched | +LL | let Thing::Foo(y) = Thing::Foo(1) else { todo!() }; + | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr index 8f5adccea806d..0f06c31c468b1 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr +++ b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr @@ -42,10 +42,10 @@ LL | B, LL | C | ^ not covered = note: the matched value is of type `E` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | if let E::A = e { /* */ } - | ~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | if let E::A = e { todo!() } + | ++ ~~~~~~~~~~~ error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered --> $DIR/non-exhaustive-defined-here.rs:52:11 @@ -91,10 +91,10 @@ LL | B, LL | C | ^ not covered = note: the matched value is of type `&E` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | if let E::A = e { /* */ } - | ~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | if let E::A = e { todo!() } + | ++ ~~~~~~~~~~~ error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered --> $DIR/non-exhaustive-defined-here.rs:66:11 @@ -140,10 +140,10 @@ LL | B, LL | C | ^ not covered = note: the matched value is of type `&&mut &E` -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let E::A = e { /* */ } +help: you might want to use `if let` to ignore the variants that aren't matched | +LL | if let E::A = e { todo!() } + | ++ ~~~~~~~~~~~ error[E0004]: non-exhaustive patterns: `None` not covered --> $DIR/non-exhaustive-defined-here.rs:92:11 @@ -185,8 +185,12 @@ LL | None, = note: the matched value is of type `Opt` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let Opt::Some(ref _x) = e { /* */ } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | let _x = if let Opt::Some(ref _x) = e { _x } else { todo!() }; + | +++++++++++ +++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched + | +LL | let Opt::Some(ref _x) = e else { todo!() }; + | ++++++++++++++++ error: aborting due to 8 previous errors diff --git a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr index 74ec646e31cca..d1dacc822e942 100644 --- a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr +++ b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr @@ -15,10 +15,10 @@ LL | let (1, (Some(1), 2..=3)) = (1, (None, 2)); = 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 `(i32, (Option, i32))` -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { /* */ } +help: you might want to use `if let` to ignore the variants that aren't matched | +LL | if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { todo!() } + | ++ ~~~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr index ded3cf3ad1d44..a9159562d9d51 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr @@ -21,8 +21,12 @@ LL | | } = note: the matched value is of type `Result` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let Ok(x) = res { /* */ } +LL | let x = if let Ok(x) = res { x } else { todo!() }; + | ++++++++++ ++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched | +LL | let Ok(x) = res else { todo!() }; + | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index 897de54a7bf8c..dd090a3a5483d 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -15,7 +15,7 @@ error: `let` expressions are not supported here LL | if &let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -24,7 +24,7 @@ error: `let` expressions are not supported here LL | if !let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -33,7 +33,7 @@ error: `let` expressions are not supported here LL | if *let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -42,7 +42,7 @@ error: `let` expressions are not supported here LL | if -let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -51,7 +51,7 @@ error: `let` expressions are not supported here LL | if (let 0 = 0)? {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -60,8 +60,13 @@ error: `let` expressions are not supported here LL | if true || let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:47:13 + | +LL | if true || let 0 = 0 {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:48:17 @@ -69,8 +74,13 @@ error: `let` expressions are not supported here LL | if (true || let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:48:14 + | +LL | if (true || let 0 = 0) {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:49:25 @@ -78,8 +88,13 @@ error: `let` expressions are not supported here LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:49:22 + | +LL | if true && (true || let 0 = 0) {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:50:25 @@ -87,8 +102,13 @@ error: `let` expressions are not supported here LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:50:13 + | +LL | if true || (true && let 0 = 0) {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:53:12 @@ -96,7 +116,7 @@ error: `let` expressions are not supported here LL | if x = let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -105,7 +125,7 @@ error: `let` expressions are not supported here LL | if true..(let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -114,7 +134,7 @@ error: `let` expressions are not supported here LL | if ..(let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -123,7 +143,7 @@ error: `let` expressions are not supported here LL | if (let 0 = 0).. {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -132,7 +152,7 @@ error: `let` expressions are not supported here LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -141,7 +161,7 @@ error: `let` expressions are not supported here LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -150,7 +170,7 @@ error: `let` expressions are not supported here LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -159,7 +179,7 @@ error: `let` expressions are not supported here LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -168,7 +188,7 @@ error: `let` expressions are not supported here LL | if let true = let true = true {} | ^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -177,7 +197,7 @@ error: `let` expressions are not supported here LL | while &let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -186,7 +206,7 @@ error: `let` expressions are not supported here LL | while !let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -195,7 +215,7 @@ error: `let` expressions are not supported here LL | while *let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -204,7 +224,7 @@ error: `let` expressions are not supported here LL | while -let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -213,7 +233,7 @@ error: `let` expressions are not supported here LL | while (let 0 = 0)? {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -222,8 +242,13 @@ error: `let` expressions are not supported here LL | while true || let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:111:16 + | +LL | while true || let 0 = 0 {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:112:20 @@ -231,8 +256,13 @@ error: `let` expressions are not supported here LL | while (true || let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:112:17 + | +LL | while (true || let 0 = 0) {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:113:28 @@ -240,8 +270,13 @@ error: `let` expressions are not supported here LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:113:25 + | +LL | while true && (true || let 0 = 0) {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:114:28 @@ -249,8 +284,13 @@ error: `let` expressions are not supported here LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:114:16 + | +LL | while true || (true && let 0 = 0) {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:117:15 @@ -258,7 +298,7 @@ error: `let` expressions are not supported here LL | while x = let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -267,7 +307,7 @@ error: `let` expressions are not supported here LL | while true..(let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -276,7 +316,7 @@ error: `let` expressions are not supported here LL | while ..(let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -285,7 +325,7 @@ error: `let` expressions are not supported here LL | while (let 0 = 0).. {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -294,7 +334,7 @@ error: `let` expressions are not supported here LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -303,7 +343,7 @@ error: `let` expressions are not supported here LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -312,7 +352,7 @@ error: `let` expressions are not supported here LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -321,7 +361,7 @@ error: `let` expressions are not supported here LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -330,7 +370,7 @@ error: `let` expressions are not supported here LL | while let true = let true = true {} | ^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -339,7 +379,7 @@ error: `let` expressions are not supported here LL | &let 0 = 0; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -348,7 +388,7 @@ error: `let` expressions are not supported here LL | !let 0 = 0; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -357,7 +397,7 @@ error: `let` expressions are not supported here LL | *let 0 = 0; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -366,7 +406,7 @@ error: `let` expressions are not supported here LL | -let 0 = 0; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -375,7 +415,7 @@ error: `let` expressions are not supported here LL | (let 0 = 0)?; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -384,8 +424,13 @@ error: `let` expressions are not supported here LL | true || let 0 = 0; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:184:10 + | +LL | true || let 0 = 0; + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:185:14 @@ -393,8 +438,13 @@ error: `let` expressions are not supported here LL | (true || let 0 = 0); | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:185:11 + | +LL | (true || let 0 = 0); + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:186:22 @@ -402,8 +452,13 @@ error: `let` expressions are not supported here LL | true && (true || let 0 = 0); | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:186:19 + | +LL | true && (true || let 0 = 0); + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:189:9 @@ -411,7 +466,7 @@ error: `let` expressions are not supported here LL | x = let 0 = 0; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -420,7 +475,7 @@ error: `let` expressions are not supported here LL | true..(let 0 = 0); | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -429,7 +484,7 @@ error: `let` expressions are not supported here LL | ..(let 0 = 0); | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -438,7 +493,7 @@ error: `let` expressions are not supported here LL | (let 0 = 0)..; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -447,7 +502,7 @@ error: `let` expressions are not supported here LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -456,7 +511,7 @@ error: `let` expressions are not supported here LL | (let true = let true = true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -465,7 +520,7 @@ error: `let` expressions are not supported here LL | &let 0 = 0 | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -474,7 +529,7 @@ error: `let` expressions are not supported here LL | true && let 1 = 1 | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -483,7 +538,7 @@ error: `let` expressions are not supported here LL | true && let 1 = 1 | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -492,7 +547,7 @@ error: `let` expressions are not supported here LL | true && let 1 = 1 | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -501,7 +556,7 @@ error: `let` expressions are not supported here LL | true && let 1 = 1 | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error[E0308]: mismatched types diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.rs b/src/test/ui/uninhabited/uninhabited-irrefutable.rs index 48cd92719b49a..661b5486adc12 100644 --- a/src/test/ui/uninhabited/uninhabited-irrefutable.rs +++ b/src/test/ui/uninhabited/uninhabited-irrefutable.rs @@ -19,10 +19,10 @@ enum Foo { A(foo::SecretlyEmpty), B(foo::NotSoSecretlyEmpty), C(NotSoSecretlyEmpty), - D(u32), + D(u32, u32), } fn main() { - let x: Foo = Foo::D(123); - let Foo::D(_y) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered + let x: Foo = Foo::D(123, 456); + let Foo::D(_y, _z) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered } diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr index ad19c34a40a11..c571e17a7b372 100644 --- a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr +++ b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr @@ -1,8 +1,8 @@ error[E0005]: refutable pattern in local binding: `A(_)` not covered --> $DIR/uninhabited-irrefutable.rs:27:9 | -LL | let Foo::D(_y) = x; - | ^^^^^^^^^^ pattern `A(_)` not covered +LL | let Foo::D(_y, _z) = x; + | ^^^^^^^^^^^^^^ pattern `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 @@ -16,8 +16,12 @@ LL | A(foo::SecretlyEmpty), = note: the matched value is of type `Foo` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let Foo::D(_y) = x { /* */ } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | let (_y, _z) = if let Foo::D(_y, _z) = x { (_y, _z) } else { todo!() }; + | +++++++++++++++++ +++++++++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched + | +LL | let Foo::D(_y, _z) = x else { todo!() }; + | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr index d90075d82f47b..74216d265d034 100644 --- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr +++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr @@ -132,8 +132,12 @@ LL | | } = note: the matched value is of type `Result` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let Ok(x) = x { /* */ } +LL | let x = if let Ok(x) = x { x } else { todo!() }; + | ++++++++++ ++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched | +LL | let Ok(x) = x else { todo!() }; + | ++++++++++++++++ error: aborting due to 7 previous errors