Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 01ad0ad

Browse files
committedMar 10, 2022
Auto merge of rust-lang#94787 - matthiaskrgr:rollup-yyou15f, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#91804 (Make some `Clone` impls `const`) - rust-lang#92541 (Mention intent of `From` trait in its docs) - rust-lang#93057 (Add Iterator::collect_into) - rust-lang#94739 (Suggest `if let`/`let_else` for refutable pat in `let`) - rust-lang#94754 (Warn users about `||` in let chain expressions) - rust-lang#94763 (Add documentation about lifetimes to thread::scope.) - rust-lang#94768 (Ignore `close_read_wakes_up` test on SGX platform) - rust-lang#94772 (Add miri to the well known conditional compilation names and values) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 85ce7fd + 94f5f1f commit 01ad0ad

36 files changed

+527
-173
lines changed
 

‎compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 65 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ struct AstValidator<'a> {
6464
/// certain positions.
6565
is_assoc_ty_bound_banned: bool,
6666

67-
/// Used to allow `let` expressions in certain syntactic locations.
68-
is_let_allowed: bool,
67+
/// See [ForbiddenLetReason]
68+
forbidden_let_reason: Option<ForbiddenLetReason>,
6969

7070
lint_buffer: &'a mut LintBuffer,
7171
}
@@ -103,20 +103,28 @@ impl<'a> AstValidator<'a> {
103103
self.is_tilde_const_allowed = old;
104104
}
105105

106-
fn with_let_allowed(&mut self, allowed: bool, f: impl FnOnce(&mut Self, bool)) {
107-
let old = mem::replace(&mut self.is_let_allowed, allowed);
106+
fn with_let_management(
107+
&mut self,
108+
forbidden_let_reason: Option<ForbiddenLetReason>,
109+
f: impl FnOnce(&mut Self, Option<ForbiddenLetReason>),
110+
) {
111+
let old = mem::replace(&mut self.forbidden_let_reason, forbidden_let_reason);
108112
f(self, old);
109-
self.is_let_allowed = old;
113+
self.forbidden_let_reason = old;
110114
}
111115

112116
/// Emits an error banning the `let` expression provided in the given location.
113-
fn ban_let_expr(&self, expr: &'a Expr) {
117+
fn ban_let_expr(&self, expr: &'a Expr, forbidden_let_reason: ForbiddenLetReason) {
114118
let sess = &self.session;
115119
if sess.opts.unstable_features.is_nightly_build() {
116-
sess.struct_span_err(expr.span, "`let` expressions are not supported here")
117-
.note("only supported directly in conditions of `if`- and `while`-expressions")
118-
.note("as well as when nested within `&&` and parentheses in those conditions")
119-
.emit();
120+
let err = "`let` expressions are not supported here";
121+
let mut diag = sess.struct_span_err(expr.span, err);
122+
diag.note("only supported directly in conditions of `if` and `while` expressions");
123+
diag.note("as well as when nested within `&&` and parentheses in those conditions");
124+
if let ForbiddenLetReason::ForbiddenWithOr(span) = forbidden_let_reason {
125+
diag.span_note(span, "`||` operators are not allowed in let chain expressions");
126+
}
127+
diag.emit();
120128
} else {
121129
sess.struct_span_err(expr.span, "expected expression, found statement (`let`)")
122130
.note("variable declaration using `let` is a statement")
@@ -988,39 +996,48 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
988996
}
989997

990998
fn visit_expr(&mut self, expr: &'a Expr) {
991-
self.with_let_allowed(false, |this, let_allowed| match &expr.kind {
992-
ExprKind::If(cond, then, opt_else) => {
993-
this.visit_block(then);
994-
walk_list!(this, visit_expr, opt_else);
995-
this.with_let_allowed(true, |this, _| this.visit_expr(cond));
996-
return;
997-
}
998-
ExprKind::Let(..) if !let_allowed => this.ban_let_expr(expr),
999-
ExprKind::Match(expr, arms) => {
1000-
this.visit_expr(expr);
1001-
for arm in arms {
1002-
this.visit_expr(&arm.body);
1003-
this.visit_pat(&arm.pat);
1004-
walk_list!(this, visit_attribute, &arm.attrs);
1005-
if let Some(ref guard) = arm.guard {
1006-
if let ExprKind::Let(_, ref expr, _) = guard.kind {
1007-
this.with_let_allowed(true, |this, _| this.visit_expr(expr));
999+
self.with_let_management(Some(ForbiddenLetReason::GenericForbidden), |this, forbidden_let_reason| {
1000+
match &expr.kind {
1001+
ExprKind::Binary(Spanned { node: BinOpKind::Or, span }, lhs, rhs) => {
1002+
let forbidden_let_reason = Some(ForbiddenLetReason::ForbiddenWithOr(*span));
1003+
this.with_let_management(forbidden_let_reason, |this, _| this.visit_expr(lhs));
1004+
this.with_let_management(forbidden_let_reason, |this, _| this.visit_expr(rhs));
1005+
}
1006+
ExprKind::If(cond, then, opt_else) => {
1007+
this.visit_block(then);
1008+
walk_list!(this, visit_expr, opt_else);
1009+
this.with_let_management(None, |this, _| this.visit_expr(cond));
1010+
return;
1011+
}
1012+
ExprKind::Let(..) if let Some(elem) = forbidden_let_reason => {
1013+
this.ban_let_expr(expr, elem);
1014+
},
1015+
ExprKind::Match(scrutinee, arms) => {
1016+
this.visit_expr(scrutinee);
1017+
for arm in arms {
1018+
this.visit_expr(&arm.body);
1019+
this.visit_pat(&arm.pat);
1020+
walk_list!(this, visit_attribute, &arm.attrs);
1021+
if let Some(guard) = &arm.guard && let ExprKind::Let(_, guard_expr, _) = &guard.kind {
1022+
this.with_let_management(None, |this, _| {
1023+
this.visit_expr(guard_expr)
1024+
});
10081025
return;
10091026
}
10101027
}
10111028
}
1029+
ExprKind::Paren(_) | ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, ..) => {
1030+
this.with_let_management(forbidden_let_reason, |this, _| visit::walk_expr(this, expr));
1031+
return;
1032+
}
1033+
ExprKind::While(cond, then, opt_label) => {
1034+
walk_list!(this, visit_label, opt_label);
1035+
this.visit_block(then);
1036+
this.with_let_management(None, |this, _| this.visit_expr(cond));
1037+
return;
1038+
}
1039+
_ => visit::walk_expr(this, expr),
10121040
}
1013-
ExprKind::Paren(_) | ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, ..) => {
1014-
this.with_let_allowed(let_allowed, |this, _| visit::walk_expr(this, expr));
1015-
return;
1016-
}
1017-
ExprKind::While(cond, then, opt_label) => {
1018-
walk_list!(this, visit_label, opt_label);
1019-
this.visit_block(then);
1020-
this.with_let_allowed(true, |this, _| this.visit_expr(cond));
1021-
return;
1022-
}
1023-
_ => visit::walk_expr(this, expr),
10241041
});
10251042
}
10261043

@@ -1772,10 +1789,19 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
17721789
is_tilde_const_allowed: false,
17731790
is_impl_trait_banned: false,
17741791
is_assoc_ty_bound_banned: false,
1775-
is_let_allowed: false,
1792+
forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden),
17761793
lint_buffer: lints,
17771794
};
17781795
visit::walk_crate(&mut validator, krate);
17791796

17801797
validator.has_proc_macro_decls
17811798
}
1799+
1800+
/// Used to forbid `let` expressions in certain syntactic locations.
1801+
#[derive(Clone, Copy)]
1802+
enum ForbiddenLetReason {
1803+
/// A let chain with the `||` operator
1804+
ForbiddenWithOr(Span),
1805+
/// `let` is not valid and the source environment is not important
1806+
GenericForbidden,
1807+
}

‎compiler/rustc_ast_passes/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
//!
55
//! The crate also contains other misc AST visitors, e.g. `node_count` and `show_span`.
66
7-
#![feature(iter_is_partitioned)]
7+
#![allow(rustc::potential_query_instability)]
88
#![feature(box_patterns)]
9+
#![feature(if_let_guard)]
10+
#![feature(iter_is_partitioned)]
11+
#![feature(let_chains)]
912
#![feature(let_else)]
1013
#![recursion_limit = "256"]
11-
#![allow(rustc::potential_query_instability)]
1214

1315
pub mod ast_validation;
1416
pub mod feature_gate;

‎compiler/rustc_mir_build/src/thir/pattern/check_match.rs

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use super::{PatCtxt, PatternError};
77
use rustc_arena::TypedArena;
88
use rustc_ast::Mutability;
99
use rustc_errors::{
10-
error_code, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
10+
error_code, pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder,
11+
ErrorGuaranteed,
1112
};
1213
use rustc_hir as hir;
1314
use rustc_hir::def::*;
@@ -20,7 +21,7 @@ use rustc_session::lint::builtin::{
2021
};
2122
use rustc_session::Session;
2223
use rustc_span::source_map::Spanned;
23-
use rustc_span::{DesugaringKind, ExpnKind, MultiSpan, Span};
24+
use rustc_span::{BytePos, DesugaringKind, ExpnKind, MultiSpan, Span};
2425

2526
crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
2627
let body_id = match def_id.as_local() {
@@ -241,6 +242,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
241242
}
242243

243244
let joined_patterns = joined_uncovered_patterns(&cx, &witnesses);
245+
246+
let mut bindings = vec![];
247+
244248
let mut err = struct_span_err!(
245249
self.tcx.sess,
246250
pat.span,
@@ -257,6 +261,16 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
257261
false
258262
}
259263
_ => {
264+
pat.walk(&mut |pat: &hir::Pat<'_>| {
265+
match pat.kind {
266+
hir::PatKind::Binding(_, _, ident, _) => {
267+
bindings.push(ident);
268+
}
269+
_ => {}
270+
}
271+
true
272+
});
273+
260274
err.span_label(pat.span, pattern_not_covered_label(&witnesses, &joined_patterns));
261275
true
262276
}
@@ -267,13 +281,71 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
267281
"`let` bindings require an \"irrefutable pattern\", like a `struct` or \
268282
an `enum` with only one variant",
269283
);
270-
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
271-
err.span_suggestion(
272-
span,
273-
"you might want to use `if let` to ignore the variant that isn't matched",
274-
format!("if {} {{ /* */ }}", &snippet[..snippet.len() - 1]),
284+
if self.tcx.sess.source_map().span_to_snippet(span).is_ok() {
285+
let semi_span = span.shrink_to_hi().with_lo(span.hi() - BytePos(1));
286+
let start_span = span.shrink_to_lo();
287+
let end_span = semi_span.shrink_to_lo();
288+
err.multipart_suggestion(
289+
&format!(
290+
"you might want to use `if let` to ignore the variant{} that {} matched",
291+
pluralize!(witnesses.len()),
292+
match witnesses.len() {
293+
1 => "isn't",
294+
_ => "aren't",
295+
},
296+
),
297+
vec![
298+
match &bindings[..] {
299+
[] => (start_span, "if ".to_string()),
300+
[binding] => (start_span, format!("let {} = if ", binding)),
301+
bindings => (
302+
start_span,
303+
format!(
304+
"let ({}) = if ",
305+
bindings
306+
.iter()
307+
.map(|ident| ident.to_string())
308+
.collect::<Vec<_>>()
309+
.join(", ")
310+
),
311+
),
312+
},
313+
match &bindings[..] {
314+
[] => (semi_span, " { todo!() }".to_string()),
315+
[binding] => {
316+
(end_span, format!(" {{ {} }} else {{ todo!() }}", binding))
317+
}
318+
bindings => (
319+
end_span,
320+
format!(
321+
" {{ ({}) }} else {{ todo!() }}",
322+
bindings
323+
.iter()
324+
.map(|ident| ident.to_string())
325+
.collect::<Vec<_>>()
326+
.join(", ")
327+
),
328+
),
329+
},
330+
],
275331
Applicability::HasPlaceholders,
276332
);
333+
if !bindings.is_empty() && cx.tcx.sess.is_nightly_build() {
334+
err.span_suggestion_verbose(
335+
semi_span.shrink_to_lo(),
336+
&format!(
337+
"alternatively, on nightly, you might want to use \
338+
`#![feature(let_else)]` to handle the variant{} that {} matched",
339+
pluralize!(witnesses.len()),
340+
match witnesses.len() {
341+
1 => "isn't",
342+
_ => "aren't",
343+
},
344+
),
345+
" else { todo!() }".to_string(),
346+
Applicability::HasPlaceholders,
347+
);
348+
}
277349
}
278350
err.note(
279351
"for more information, visit \

‎compiler/rustc_session/src/config.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,7 @@ impl CrateCheckConfig {
10721072
// NOTE: This should be kept in sync with `default_configuration` and
10731073
// `fill_well_known_values`
10741074
const WELL_KNOWN_NAMES: &[Symbol] = &[
1075+
// rustc
10751076
sym::unix,
10761077
sym::windows,
10771078
sym::target_os,
@@ -1091,9 +1092,12 @@ impl CrateCheckConfig {
10911092
sym::debug_assertions,
10921093
sym::proc_macro,
10931094
sym::test,
1095+
sym::feature,
1096+
// rustdoc
10941097
sym::doc,
10951098
sym::doctest,
1096-
sym::feature,
1099+
// miri
1100+
sym::miri,
10971101
];
10981102

10991103
// We only insert well-known names if `names()` was activated
@@ -1128,13 +1132,14 @@ impl CrateCheckConfig {
11281132

11291133
// No-values
11301134
for name in [
1135+
sym::doc,
1136+
sym::miri,
11311137
sym::unix,
1132-
sym::windows,
1133-
sym::debug_assertions,
1134-
sym::proc_macro,
11351138
sym::test,
1136-
sym::doc,
11371139
sym::doctest,
1140+
sym::windows,
1141+
sym::proc_macro,
1142+
sym::debug_assertions,
11381143
sym::target_thread_local,
11391144
] {
11401145
self.values_valid.entry(name).or_default();

‎compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,7 @@ symbols! {
891891
minnumf32,
892892
minnumf64,
893893
mips_target_feature,
894+
miri,
894895
misc,
895896
mmx_reg,
896897
modifiers,

‎library/core/src/clone.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,11 @@ pub trait Clone: Sized {
127127
/// allocations.
128128
#[inline]
129129
#[stable(feature = "rust1", since = "1.0.0")]
130-
fn clone_from(&mut self, source: &Self) {
130+
#[default_method_body_is_const]
131+
fn clone_from(&mut self, source: &Self)
132+
where
133+
Self: ~const Drop,
134+
{
131135
*self = source.clone()
132136
}
133137
}
@@ -178,7 +182,8 @@ mod impls {
178182
($($t:ty)*) => {
179183
$(
180184
#[stable(feature = "rust1", since = "1.0.0")]
181-
impl Clone for $t {
185+
#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
186+
impl const Clone for $t {
182187
#[inline]
183188
fn clone(&self) -> Self {
184189
*self
@@ -196,23 +201,26 @@ mod impls {
196201
}
197202

198203
#[unstable(feature = "never_type", issue = "35121")]
199-
impl Clone for ! {
204+
#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
205+
impl const Clone for ! {
200206
#[inline]
201207
fn clone(&self) -> Self {
202208
*self
203209
}
204210
}
205211

206212
#[stable(feature = "rust1", since = "1.0.0")]
207-
impl<T: ?Sized> Clone for *const T {
213+
#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
214+
impl<T: ?Sized> const Clone for *const T {
208215
#[inline]
209216
fn clone(&self) -> Self {
210217
*self
211218
}
212219
}
213220

214221
#[stable(feature = "rust1", since = "1.0.0")]
215-
impl<T: ?Sized> Clone for *mut T {
222+
#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
223+
impl<T: ?Sized> const Clone for *mut T {
216224
#[inline]
217225
fn clone(&self) -> Self {
218226
*self
@@ -221,7 +229,8 @@ mod impls {
221229

222230
/// Shared references can be cloned, but mutable references *cannot*!
223231
#[stable(feature = "rust1", since = "1.0.0")]
224-
impl<T: ?Sized> Clone for &T {
232+
#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
233+
impl<T: ?Sized> const Clone for &T {
225234
#[inline]
226235
#[rustc_diagnostic_item = "noop_method_clone"]
227236
fn clone(&self) -> Self {

‎library/core/src/convert/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,8 @@ pub trait Into<T>: Sized {
300300
/// that encapsulate multiple error types. See the "Examples" section and [the book][book] for more
301301
/// details.
302302
///
303-
/// **Note: This trait must not fail**. If the conversion can fail, use [`TryFrom`].
303+
/// **Note: This trait must not fail**. The `From` trait is intended for perfect conversions.
304+
/// If the conversion can fail or is not perfect, use [`TryFrom`].
304305
///
305306
/// # Generic Implementations
306307
///
@@ -690,7 +691,8 @@ impl AsMut<str> for str {
690691
pub enum Infallible {}
691692

692693
#[stable(feature = "convert_infallible", since = "1.34.0")]
693-
impl Clone for Infallible {
694+
#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
695+
impl const Clone for Infallible {
694696
fn clone(&self) -> Infallible {
695697
match *self {}
696698
}

‎library/core/src/iter/traits/iterator.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,6 +1859,77 @@ pub trait Iterator {
18591859
try_process(self, |i| i.collect())
18601860
}
18611861

1862+
/// Collects all the items from an iterator into a collection.
1863+
///
1864+
/// This method consumes the iterator and adds all its items to the
1865+
/// passed collection. The collection is then returned, so the call chain
1866+
/// can be continued.
1867+
///
1868+
/// This is useful when you already have a collection and wants to add
1869+
/// the iterator items to it.
1870+
///
1871+
/// This method is a convenience method to call [Extend::extend](trait.Extend.html),
1872+
/// but instead of being called on a collection, it's called on an iterator.
1873+
///
1874+
/// # Examples
1875+
///
1876+
/// Basic usage:
1877+
///
1878+
/// ```
1879+
/// #![feature(iter_collect_into)]
1880+
///
1881+
/// let a = [1, 2, 3];
1882+
/// let mut vec: Vec::<i32> = vec![0, 1];
1883+
///
1884+
/// a.iter().map(|&x| x * 2).collect_into(&mut vec);
1885+
/// a.iter().map(|&x| x * 10).collect_into(&mut vec);
1886+
///
1887+
/// assert_eq!(vec![0, 1, 2, 4, 6, 10, 20, 30], vec);
1888+
/// ```
1889+
///
1890+
/// `Vec` can have a manual set capacity to avoid reallocating it:
1891+
///
1892+
/// ```
1893+
/// #![feature(iter_collect_into)]
1894+
///
1895+
/// let a = [1, 2, 3];
1896+
/// let mut vec: Vec::<i32> = Vec::with_capacity(6);
1897+
///
1898+
/// a.iter().map(|&x| x * 2).collect_into(&mut vec);
1899+
/// a.iter().map(|&x| x * 10).collect_into(&mut vec);
1900+
///
1901+
/// assert_eq!(6, vec.capacity());
1902+
/// println!("{:?}", vec);
1903+
/// ```
1904+
///
1905+
/// The returned mutable reference can be used to continue the call chain:
1906+
///
1907+
/// ```
1908+
/// #![feature(iter_collect_into)]
1909+
///
1910+
/// let a = [1, 2, 3];
1911+
/// let mut vec: Vec::<i32> = Vec::with_capacity(6);
1912+
///
1913+
/// let count = a.iter().collect_into(&mut vec).iter().count();
1914+
///
1915+
/// assert_eq!(count, vec.len());
1916+
/// println!("Vec len is {}", count);
1917+
///
1918+
/// let count = a.iter().collect_into(&mut vec).iter().count();
1919+
///
1920+
/// assert_eq!(count, vec.len());
1921+
/// println!("Vec len now is {}", count);
1922+
/// ```
1923+
#[inline]
1924+
#[unstable(feature = "iter_collect_into", reason = "new API", issue = "94780")]
1925+
fn collect_into<E: Extend<Self::Item>>(self, collection: &mut E) -> &mut E
1926+
where
1927+
Self: Sized,
1928+
{
1929+
collection.extend(self);
1930+
collection
1931+
}
1932+
18621933
/// Consumes an iterator, creating two collections from it.
18631934
///
18641935
/// The predicate passed to `partition()` can return `true`, or `false`.

‎library/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
#![feature(const_caller_location)]
105105
#![feature(const_cell_into_inner)]
106106
#![feature(const_char_convert)]
107+
#![feature(const_clone)]
107108
#![feature(const_discriminant)]
108109
#![feature(const_eval_select)]
109110
#![feature(const_float_bits_conv)]

‎library/core/src/option.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1857,7 +1857,11 @@ const fn expect_failed(msg: &str) -> ! {
18571857
/////////////////////////////////////////////////////////////////////////////
18581858

18591859
#[stable(feature = "rust1", since = "1.0.0")]
1860-
impl<T: Clone> Clone for Option<T> {
1860+
#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
1861+
impl<T> const Clone for Option<T>
1862+
where
1863+
T: ~const Clone + ~const Drop,
1864+
{
18611865
#[inline]
18621866
fn clone(&self) -> Self {
18631867
match self {

‎library/core/src/ptr/non_null.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,8 @@ impl<T> NonNull<[T]> {
642642
}
643643

644644
#[stable(feature = "nonnull", since = "1.25.0")]
645-
impl<T: ?Sized> Clone for NonNull<T> {
645+
#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
646+
impl<T: ?Sized> const Clone for NonNull<T> {
646647
#[inline]
647648
fn clone(&self) -> Self {
648649
*self

‎library/core/src/ptr/unique.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ impl<T: ?Sized> Unique<T> {
146146
}
147147

148148
#[unstable(feature = "ptr_internals", issue = "none")]
149-
impl<T: ?Sized> Clone for Unique<T> {
149+
#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
150+
impl<T: ?Sized> const Clone for Unique<T> {
150151
#[inline]
151152
fn clone(&self) -> Self {
152153
*self

‎library/core/src/result.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1801,7 +1801,12 @@ fn unwrap_failed<T>(_msg: &str, _error: &T) -> ! {
18011801
/////////////////////////////////////////////////////////////////////////////
18021802

18031803
#[stable(feature = "rust1", since = "1.0.0")]
1804-
impl<T: Clone, E: Clone> Clone for Result<T, E> {
1804+
#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
1805+
impl<T, E> const Clone for Result<T, E>
1806+
where
1807+
T: ~const Clone + ~const Drop,
1808+
E: ~const Clone + ~const Drop,
1809+
{
18051810
#[inline]
18061811
fn clone(&self) -> Self {
18071812
match self {

‎library/core/tests/iter/traits/iterator.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,14 @@ fn test_try_collect() {
543543
assert_eq!(v, Continue(vec![4, 5]));
544544
}
545545

546+
#[test]
547+
fn test_collect_into() {
548+
let a = vec![1, 2, 3, 4, 5];
549+
let mut b = Vec::new();
550+
a.iter().cloned().collect_into(&mut b);
551+
assert!(a == b);
552+
}
553+
546554
// just tests by whether or not this compiles
547555
fn _empty_impl_all_auto_traits<T>() {
548556
use std::panic::{RefUnwindSafe, UnwindSafe};

‎library/core/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
#![feature(slice_partition_dedup)]
6363
#![feature(int_log)]
6464
#![feature(iter_advance_by)]
65+
#![feature(iter_collect_into)]
6566
#![feature(iter_partition_in_place)]
6667
#![feature(iter_intersperse)]
6768
#![feature(iter_is_partitioned)]

‎library/std/src/net/tcp/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ fn close_readwrite_smoke() {
508508
}
509509

510510
#[test]
511+
#[cfg_attr(target_env = "sgx", ignore)]
511512
fn close_read_wakes_up() {
512513
each_ip(&mut |addr| {
513514
let a = t!(TcpListener::bind(&addr));

‎library/std/src/thread/scoped.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,24 @@ impl ScopeData {
107107
/// a.push(4);
108108
/// assert_eq!(x, a.len());
109109
/// ```
110+
///
111+
/// # Lifetimes
112+
///
113+
/// Scoped threads involve two lifetimes: `'scope` and `'env`.
114+
///
115+
/// The `'scope` lifetime represents the lifetime of the scope itself.
116+
/// That is: the time during which new scoped threads may be spawned,
117+
/// and also the time during which they might still be running.
118+
/// Once this lifetime ends, all scoped threads are joined.
119+
/// This lifetime starts within the `scope` function, before `f` (the argument to `scope`) starts.
120+
/// It ends after `f` returns and all scoped threads have been joined, but before `scope` returns.
121+
///
122+
/// The `'env` lifetime represents the lifetime of whatever is borrowed by the scoped threads.
123+
/// This lifetime must outlast the call to `scope`, and thus cannot be smaller than `'scope`.
124+
/// It can be as small as the call to `scope`, meaning that anything that outlives this call,
125+
/// such as local variables defined right before the scope, can be borrowed by the scoped threads.
126+
///
127+
/// The `'env: 'scope` bound is part of the definition of the `Scope` type.
110128
#[track_caller]
111129
pub fn scope<'env, F, T>(f: F) -> T
112130
where

‎src/bootstrap/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,6 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
193193
(None, "bootstrap", None),
194194
(Some(Mode::Rustc), "parallel_compiler", None),
195195
(Some(Mode::ToolRustc), "parallel_compiler", None),
196-
(Some(Mode::Std), "miri", None),
197196
(Some(Mode::Std), "stdarch_intel_sde", None),
198197
(Some(Mode::Std), "no_fp_fmt_parse", None),
199198
(Some(Mode::Std), "no_global_oom_handling", None),

‎src/test/ui/check-cfg/well-known-names.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,10 @@ fn unix_misspell() {}
2424
#[cfg(unix)]
2525
fn unix() {}
2626

27+
#[cfg(miri)]
28+
fn miri() {}
29+
30+
#[cfg(doc)]
31+
fn doc() {}
32+
2733
fn main() {}

‎src/test/ui/check-cfg/well-known-values.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,18 @@ fn unix_with_value() {}
2525
#[cfg(unix)]
2626
fn unix() {}
2727

28+
#[cfg(miri = "miri")]
29+
//~^ WARNING unexpected `cfg` condition value
30+
fn miri_with_value() {}
31+
32+
#[cfg(miri)]
33+
fn miri() {}
34+
35+
#[cfg(doc = "linux")]
36+
//~^ WARNING unexpected `cfg` condition value
37+
fn doc_with_value() {}
38+
39+
#[cfg(doc)]
40+
fn doc() {}
41+
2842
fn main() {}

‎src/test/ui/check-cfg/well-known-values.stderr

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,25 @@ LL | #[cfg(unix = "aa")]
2929
|
3030
= note: no expected value for `unix`
3131

32-
warning: 3 warnings emitted
32+
warning: unexpected `cfg` condition value
33+
--> $DIR/well-known-values.rs:28:7
34+
|
35+
LL | #[cfg(miri = "miri")]
36+
| ^^^^---------
37+
| |
38+
| help: remove the value
39+
|
40+
= note: no expected value for `miri`
41+
42+
warning: unexpected `cfg` condition value
43+
--> $DIR/well-known-values.rs:35:7
44+
|
45+
LL | #[cfg(doc = "linux")]
46+
| ^^^----------
47+
| |
48+
| help: remove the value
49+
|
50+
= note: no expected value for `doc`
51+
52+
warning: 5 warnings emitted
3353

‎src/test/ui/consts/const-match-check.eval1.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ LL | A = { let 0 = 0; 0 },
77
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
88
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
99
= note: the matched value is of type `i32`
10-
help: you might want to use `if let` to ignore the variant that isn't matched
10+
help: you might want to use `if let` to ignore the variants that aren't matched
1111
|
12-
LL | A = { if let 0 = 0 { /* */ } 0 },
13-
| ~~~~~~~~~~~~~~~~~~~~~~
12+
LL | A = { if let 0 = 0 { todo!() } 0 },
13+
| ++ ~~~~~~~~~~~
1414

1515
error: aborting due to previous error
1616

‎src/test/ui/consts/const-match-check.eval2.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ LL | let x: [i32; { let 0 = 0; 0 }] = [];
77
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
88
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
99
= note: the matched value is of type `i32`
10-
help: you might want to use `if let` to ignore the variant that isn't matched
10+
help: you might want to use `if let` to ignore the variants that aren't matched
1111
|
12-
LL | let x: [i32; { if let 0 = 0 { /* */ } 0 }] = [];
13-
| ~~~~~~~~~~~~~~~~~~~~~~
12+
LL | let x: [i32; { if let 0 = 0 { todo!() } 0 }] = [];
13+
| ++ ~~~~~~~~~~~
1414

1515
error: aborting due to previous error
1616

‎src/test/ui/consts/const-match-check.matchck.stderr

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ LL | const X: i32 = { let 0 = 0; 0 };
77
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
88
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
99
= note: the matched value is of type `i32`
10-
help: you might want to use `if let` to ignore the variant that isn't matched
10+
help: you might want to use `if let` to ignore the variants that aren't matched
1111
|
12-
LL | const X: i32 = { if let 0 = 0 { /* */ } 0 };
13-
| ~~~~~~~~~~~~~~~~~~~~~~
12+
LL | const X: i32 = { if let 0 = 0 { todo!() } 0 };
13+
| ++ ~~~~~~~~~~~
1414

1515
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
1616
--> $DIR/const-match-check.rs:8:23
@@ -21,10 +21,10 @@ LL | static Y: i32 = { let 0 = 0; 0 };
2121
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
2222
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
2323
= note: the matched value is of type `i32`
24-
help: you might want to use `if let` to ignore the variant that isn't matched
24+
help: you might want to use `if let` to ignore the variants that aren't matched
2525
|
26-
LL | static Y: i32 = { if let 0 = 0 { /* */ } 0 };
27-
| ~~~~~~~~~~~~~~~~~~~~~~
26+
LL | static Y: i32 = { if let 0 = 0 { todo!() } 0 };
27+
| ++ ~~~~~~~~~~~
2828

2929
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
3030
--> $DIR/const-match-check.rs:13:26
@@ -35,10 +35,10 @@ LL | const X: i32 = { let 0 = 0; 0 };
3535
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
3636
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
3737
= note: the matched value is of type `i32`
38-
help: you might want to use `if let` to ignore the variant that isn't matched
38+
help: you might want to use `if let` to ignore the variants that aren't matched
3939
|
40-
LL | const X: i32 = { if let 0 = 0 { /* */ } 0 };
41-
| ~~~~~~~~~~~~~~~~~~~~~~
40+
LL | const X: i32 = { if let 0 = 0 { todo!() } 0 };
41+
| ++ ~~~~~~~~~~~
4242

4343
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
4444
--> $DIR/const-match-check.rs:19:26
@@ -49,10 +49,10 @@ LL | const X: i32 = { let 0 = 0; 0 };
4949
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
5050
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
5151
= note: the matched value is of type `i32`
52-
help: you might want to use `if let` to ignore the variant that isn't matched
52+
help: you might want to use `if let` to ignore the variants that aren't matched
5353
|
54-
LL | const X: i32 = { if let 0 = 0 { /* */ } 0 };
55-
| ~~~~~~~~~~~~~~~~~~~~~~
54+
LL | const X: i32 = { if let 0 = 0 { todo!() } 0 };
55+
| ++ ~~~~~~~~~~~
5656

5757
error: aborting due to 4 previous errors
5858

‎src/test/ui/empty/empty-never-array.stderr

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@ LL | T(T, [!; 0]),
1616
= note: the matched value is of type `Helper<T, U>`
1717
help: you might want to use `if let` to ignore the variant that isn't matched
1818
|
19-
LL | if let Helper::U(u) = Helper::T(t, []) { /* */ }
19+
LL | let u = if let Helper::U(u) = Helper::T(t, []) { u } else { todo!() };
20+
| ++++++++++ ++++++++++++++++++++++
21+
help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
2022
|
23+
LL | let Helper::U(u) = Helper::T(t, []) else { todo!() };
24+
| ++++++++++++++++
2125

2226
error: aborting due to previous error
2327

‎src/test/ui/error-codes/E0005.stderr

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,12 @@ LL | | }
2222
= note: the matched value is of type `Option<i32>`
2323
help: you might want to use `if let` to ignore the variant that isn't matched
2424
|
25-
LL | if let Some(y) = x { /* */ }
26-
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25+
LL | let y = if let Some(y) = x { y } else { todo!() };
26+
| ++++++++++ ++++++++++++++++++++++
27+
help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
28+
|
29+
LL | let Some(y) = x else { todo!() };
30+
| ++++++++++++++++
2731

2832
error: aborting due to previous error
2933

‎src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@ LL | | }
2121
= note: the matched value is of type `Result<u32, !>`
2222
help: you might want to use `if let` to ignore the variant that isn't matched
2323
|
24-
LL | if let Ok(_x) = foo() { /* */ }
25-
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24+
LL | let _x = if let Ok(_x) = foo() { _x } else { todo!() };
25+
| +++++++++++ +++++++++++++++++++++++
26+
help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
27+
|
28+
LL | let Ok(_x) = foo() else { todo!() };
29+
| ++++++++++++++++
2630

2731
error: aborting due to previous error
2832

‎src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ LL | let (0 | (1 | 2)) = 0;
77
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
88
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
99
= note: the matched value is of type `i32`
10-
help: you might want to use `if let` to ignore the variant that isn't matched
10+
help: you might want to use `if let` to ignore the variants that aren't matched
1111
|
12-
LL | if let (0 | (1 | 2)) = 0 { /* */ }
13-
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12+
LL | if let (0 | (1 | 2)) = 0 { todo!() }
13+
| ++ ~~~~~~~~~~~
1414

1515
error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered
1616
--> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:3:11

‎src/test/ui/pattern/usefulness/issue-31561.stderr

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@ LL | Bar,
1717
LL | Baz
1818
| ^^^ not covered
1919
= note: the matched value is of type `Thing`
20-
help: you might want to use `if let` to ignore the variant that isn't matched
20+
help: you might want to use `if let` to ignore the variants that aren't matched
2121
|
22-
LL | if let Thing::Foo(y) = Thing::Foo(1) { /* */ }
22+
LL | let y = if let Thing::Foo(y) = Thing::Foo(1) { y } else { todo!() };
23+
| ++++++++++ ++++++++++++++++++++++
24+
help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
2325
|
26+
LL | let Thing::Foo(y) = Thing::Foo(1) else { todo!() };
27+
| ++++++++++++++++
2428

2529
error: aborting due to previous error
2630

‎src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ LL | B,
4242
LL | C
4343
| ^ not covered
4444
= note: the matched value is of type `E`
45-
help: you might want to use `if let` to ignore the variant that isn't matched
45+
help: you might want to use `if let` to ignore the variants that aren't matched
4646
|
47-
LL | if let E::A = e { /* */ }
48-
| ~~~~~~~~~~~~~~~~~~~~~~~~~
47+
LL | if let E::A = e { todo!() }
48+
| ++ ~~~~~~~~~~~
4949

5050
error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered
5151
--> $DIR/non-exhaustive-defined-here.rs:52:11
@@ -91,10 +91,10 @@ LL | B,
9191
LL | C
9292
| ^ not covered
9393
= note: the matched value is of type `&E`
94-
help: you might want to use `if let` to ignore the variant that isn't matched
94+
help: you might want to use `if let` to ignore the variants that aren't matched
9595
|
96-
LL | if let E::A = e { /* */ }
97-
| ~~~~~~~~~~~~~~~~~~~~~~~~~
96+
LL | if let E::A = e { todo!() }
97+
| ++ ~~~~~~~~~~~
9898

9999
error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered
100100
--> $DIR/non-exhaustive-defined-here.rs:66:11
@@ -140,10 +140,10 @@ LL | B,
140140
LL | C
141141
| ^ not covered
142142
= note: the matched value is of type `&&mut &E`
143-
help: you might want to use `if let` to ignore the variant that isn't matched
144-
|
145-
LL | if let E::A = e { /* */ }
143+
help: you might want to use `if let` to ignore the variants that aren't matched
146144
|
145+
LL | if let E::A = e { todo!() }
146+
| ++ ~~~~~~~~~~~
147147

148148
error[E0004]: non-exhaustive patterns: `None` not covered
149149
--> $DIR/non-exhaustive-defined-here.rs:92:11
@@ -185,8 +185,12 @@ LL | None,
185185
= note: the matched value is of type `Opt`
186186
help: you might want to use `if let` to ignore the variant that isn't matched
187187
|
188-
LL | if let Opt::Some(ref _x) = e { /* */ }
189-
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
188+
LL | let _x = if let Opt::Some(ref _x) = e { _x } else { todo!() };
189+
| +++++++++++ +++++++++++++++++++++++
190+
help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
191+
|
192+
LL | let Opt::Some(ref _x) = e else { todo!() };
193+
| ++++++++++++++++
190194

191195
error: aborting due to 8 previous errors
192196

‎src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ LL | let (1, (Some(1), 2..=3)) = (1, (None, 2));
1515
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
1616
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
1717
= note: the matched value is of type `(i32, (Option<i32>, i32))`
18-
help: you might want to use `if let` to ignore the variant that isn't matched
19-
|
20-
LL | if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { /* */ }
18+
help: you might want to use `if let` to ignore the variants that aren't matched
2119
|
20+
LL | if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { todo!() }
21+
| ++ ~~~~~~~~~~~
2222

2323
error: aborting due to 2 previous errors
2424

‎src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@ LL | | }
2121
= note: the matched value is of type `Result<u32, &R>`
2222
help: you might want to use `if let` to ignore the variant that isn't matched
2323
|
24-
LL | if let Ok(x) = res { /* */ }
24+
LL | let x = if let Ok(x) = res { x } else { todo!() };
25+
| ++++++++++ ++++++++++++++++++++++
26+
help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
2527
|
28+
LL | let Ok(x) = res else { todo!() };
29+
| ++++++++++++++++
2630

2731
error: aborting due to previous error
2832

‎src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr

Lines changed: 110 additions & 55 deletions
Large diffs are not rendered by default.

‎src/test/ui/uninhabited/uninhabited-irrefutable.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ enum Foo {
1919
A(foo::SecretlyEmpty),
2020
B(foo::NotSoSecretlyEmpty),
2121
C(NotSoSecretlyEmpty),
22-
D(u32),
22+
D(u32, u32),
2323
}
2424

2525
fn main() {
26-
let x: Foo = Foo::D(123);
27-
let Foo::D(_y) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered
26+
let x: Foo = Foo::D(123, 456);
27+
let Foo::D(_y, _z) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered
2828
}

‎src/test/ui/uninhabited/uninhabited-irrefutable.stderr

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0005]: refutable pattern in local binding: `A(_)` not covered
22
--> $DIR/uninhabited-irrefutable.rs:27:9
33
|
4-
LL | let Foo::D(_y) = x;
5-
| ^^^^^^^^^^ pattern `A(_)` not covered
4+
LL | let Foo::D(_y, _z) = x;
5+
| ^^^^^^^^^^^^^^ pattern `A(_)` not covered
66
|
77
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
88
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
@@ -16,8 +16,12 @@ LL | A(foo::SecretlyEmpty),
1616
= note: the matched value is of type `Foo`
1717
help: you might want to use `if let` to ignore the variant that isn't matched
1818
|
19-
LL | if let Foo::D(_y) = x { /* */ }
20-
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19+
LL | let (_y, _z) = if let Foo::D(_y, _z) = x { (_y, _z) } else { todo!() };
20+
| +++++++++++++++++ +++++++++++++++++++++++++++++
21+
help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
22+
|
23+
LL | let Foo::D(_y, _z) = x else { todo!() };
24+
| ++++++++++++++++
2125

2226
error: aborting due to previous error
2327

‎src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,12 @@ LL | | }
132132
= note: the matched value is of type `Result<u32, Void>`
133133
help: you might want to use `if let` to ignore the variant that isn't matched
134134
|
135-
LL | if let Ok(x) = x { /* */ }
135+
LL | let x = if let Ok(x) = x { x } else { todo!() };
136+
| ++++++++++ ++++++++++++++++++++++
137+
help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
136138
|
139+
LL | let Ok(x) = x else { todo!() };
140+
| ++++++++++++++++
137141

138142
error: aborting due to 7 previous errors
139143

0 commit comments

Comments
 (0)
This repository has been archived.