Skip to content

Commit d1ef818

Browse files
committed
Revert let_chains stabilization
This reverts commit 3266460. This is the revert against master, the beta revert was already done in #100538.
1 parent 76eb4f3 commit d1ef818

File tree

59 files changed

+791
-396
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+791
-396
lines changed

compiler/rustc_ast/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#![feature(const_trait_impl)]
1515
#![feature(if_let_guard)]
1616
#![cfg_attr(bootstrap, feature(label_break_value))]
17+
#![feature(let_chains)]
1718
#![feature(min_specialization)]
1819
#![feature(negative_impls)]
1920
#![feature(slice_internals)]

compiler/rustc_ast_lowering/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
//! in the HIR, especially for multiple identifiers.
3232
3333
#![feature(box_patterns)]
34+
#![feature(let_chains)]
3435
#![feature(let_else)]
3536
#![feature(never_type)]
3637
#![recursion_limit = "256"]

compiler/rustc_ast_passes/src/ast_validation.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,33 @@ impl<'a> AstValidator<'a> {
119119

120120
/// Emits an error banning the `let` expression provided in the given location.
121121
fn ban_let_expr(&self, expr: &'a Expr, forbidden_let_reason: ForbiddenLetReason) {
122-
self.session.emit_err(ForbiddenLet { span: expr.span, reason: forbidden_let_reason });
122+
let sess = &self.session;
123+
if sess.opts.unstable_features.is_nightly_build() {
124+
let err = "`let` expressions are not supported here";
125+
let mut diag = sess.struct_span_err(expr.span, err);
126+
diag.note("only supported directly in conditions of `if` and `while` expressions");
127+
match forbidden_let_reason {
128+
ForbiddenLetReason::GenericForbidden => {}
129+
ForbiddenLetReason::NotSupportedOr(span) => {
130+
diag.span_note(
131+
span,
132+
"`||` operators are not supported in let chain expressions",
133+
);
134+
}
135+
ForbiddenLetReason::NotSupportedParentheses(span) => {
136+
diag.span_note(
137+
span,
138+
"`let`s wrapped in parentheses are not supported in a context with let \
139+
chains",
140+
);
141+
}
142+
}
143+
diag.emit();
144+
} else {
145+
sess.struct_span_err(expr.span, "expected expression, found statement (`let`)")
146+
.note("variable declaration using `let` is a statement")
147+
.emit();
148+
}
123149
}
124150

125151
fn check_gat_where(

compiler/rustc_ast_passes/src/feature_gate.rs

+1
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
777777
"`if let` guards are experimental",
778778
"you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`"
779779
);
780+
gate_all!(let_chains, "`let` expressions in this position are unstable");
780781
gate_all!(
781782
async_closure,
782783
"async closures are unstable",

compiler/rustc_ast_passes/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#![feature(box_patterns)]
99
#![feature(if_let_guard)]
1010
#![feature(iter_is_partitioned)]
11+
#![feature(let_chains)]
1112
#![feature(let_else)]
1213
#![recursion_limit = "256"]
1314

compiler/rustc_attr/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! The goal is to move the definition of `MetaItem` and things that don't need to be in `syntax`
55
//! to this crate.
66
7+
#![feature(let_chains)]
78
#![feature(let_else)]
89
#![deny(rustc::untranslatable_diagnostic)]
910
#![deny(rustc::diagnostic_outside_of_impl)]

compiler/rustc_borrowck/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
#![allow(rustc::potential_query_instability)]
44
#![feature(box_patterns)]
5+
#![feature(let_chains)]
56
#![feature(let_else)]
67
#![feature(min_specialization)]
78
#![feature(never_type)]

compiler/rustc_builtin_macros/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#![feature(decl_macro)]
99
#![feature(if_let_guard)]
1010
#![feature(is_sorted)]
11+
#![feature(let_chains)]
1112
#![feature(let_else)]
1213
#![feature(proc_macro_internals)]
1314
#![feature(proc_macro_quote)]

compiler/rustc_codegen_llvm/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
88
#![feature(hash_raw_entry)]
9+
#![feature(let_chains)]
910
#![feature(let_else)]
1011
#![feature(extern_types)]
1112
#![feature(once_cell)]

compiler/rustc_const_eval/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Rust MIR: a lowered representation of Rust.
99
#![feature(control_flow_enum)]
1010
#![feature(decl_macro)]
1111
#![feature(exact_size_is_empty)]
12+
#![feature(let_chains)]
1213
#![feature(let_else)]
1314
#![feature(map_try_insert)]
1415
#![feature(min_specialization)]

compiler/rustc_error_messages/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![feature(let_chains)]
12
#![feature(once_cell)]
23
#![feature(rustc_attrs)]
34
#![feature(type_alias_impl_trait)]

compiler/rustc_errors/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#![feature(drain_filter)]
77
#![feature(if_let_guard)]
88
#![feature(adt_const_params)]
9+
#![feature(let_chains)]
910
#![feature(let_else)]
1011
#![feature(never_type)]
1112
#![feature(result_option_inspect)]

compiler/rustc_expand/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![feature(associated_type_bounds)]
33
#![feature(associated_type_defaults)]
44
#![feature(if_let_guard)]
5+
#![feature(let_chains)]
56
#![feature(let_else)]
67
#![feature(macro_metavar_expr)]
78
#![feature(proc_macro_diagnostic)]

compiler/rustc_feature/src/accepted.rs

-2
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,6 @@ declare_features! (
188188
(accepted, item_like_imports, "1.15.0", Some(35120), None),
189189
/// Allows `'a: { break 'a; }`.
190190
(accepted, label_break_value, "CURRENT_RUSTC_VERSION", Some(48594), None),
191-
/// Allows `if/while p && let q = r && ...` chains.
192-
(accepted, let_chains, "1.64.0", Some(53667), None),
193191
/// Allows `break {expr}` with a value inside `loop`s.
194192
(accepted, loop_break_value, "1.19.0", Some(37339), None),
195193
/// Allows use of `?` as the Kleene "at most one" operator in macros.

compiler/rustc_feature/src/active.rs

+2
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,8 @@ declare_features! (
422422
(active, isa_attribute, "1.48.0", Some(74727), None),
423423
// Allows setting the threshold for the `large_assignments` lint.
424424
(active, large_assignments, "1.52.0", Some(83518), None),
425+
/// Allows `if/while p && let q = r && ...` chains.
426+
(active, let_chains, "1.37.0", Some(53667), None),
425427
/// Allows `let...else` statements.
426428
(active, let_else, "1.56.0", Some(87335), None),
427429
/// Allows `#[link(..., cfg(..))]`.

compiler/rustc_infer/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#![feature(control_flow_enum)]
1919
#![feature(extend_one)]
2020
#![cfg_attr(bootstrap, feature(label_break_value))]
21+
#![feature(let_chains)]
2122
#![feature(let_else)]
2223
#![feature(min_specialization)]
2324
#![feature(never_type)]

compiler/rustc_lint/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#![feature(if_let_guard)]
3434
#![feature(iter_intersperse)]
3535
#![feature(iter_order_by)]
36+
#![feature(let_chains)]
3637
#![feature(let_else)]
3738
#![feature(never_type)]
3839
#![recursion_limit = "256"]

compiler/rustc_metadata/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![feature(generators)]
55
#![feature(generic_associated_types)]
66
#![feature(iter_from_generator)]
7+
#![feature(let_chains)]
78
#![feature(let_else)]
89
#![feature(once_cell)]
910
#![feature(proc_macro_internals)]

compiler/rustc_middle/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#![feature(extern_types)]
4040
#![feature(new_uninit)]
4141
#![feature(once_cell)]
42+
#![feature(let_chains)]
4243
#![feature(let_else)]
4344
#![feature(min_specialization)]
4445
#![feature(trusted_len)]

compiler/rustc_mir_build/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#![feature(box_patterns)]
66
#![feature(control_flow_enum)]
77
#![feature(if_let_guard)]
8+
#![feature(let_chains)]
89
#![feature(let_else)]
910
#![feature(min_specialization)]
1011
#![feature(once_cell)]

compiler/rustc_mir_transform/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![allow(rustc::potential_query_instability)]
22
#![feature(box_patterns)]
3+
#![feature(let_chains)]
34
#![feature(let_else)]
45
#![feature(map_try_insert)]
56
#![feature(min_specialization)]

compiler/rustc_parse/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#![feature(array_windows)]
44
#![feature(box_patterns)]
55
#![feature(if_let_guard)]
6+
#![feature(let_chains)]
67
#![feature(let_else)]
78
#![feature(never_type)]
89
#![feature(rustc_attrs)]

compiler/rustc_parse/src/parser/expr.rs

+22-6
Original file line numberDiff line numberDiff line change
@@ -2251,7 +2251,15 @@ impl<'a> Parser<'a> {
22512251

22522252
/// Parses the condition of a `if` or `while` expression.
22532253
fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
2254-
self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)
2254+
let cond =
2255+
self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)?;
2256+
2257+
if let ExprKind::Let(..) = cond.kind {
2258+
// Remove the last feature gating of a `let` expression since it's stable.
2259+
self.sess.gated_spans.ungate_last(sym::let_chains, cond.span);
2260+
}
2261+
2262+
Ok(cond)
22552263
}
22562264

22572265
/// Parses a `let $pat = $expr` pseudo-expression.
@@ -2280,6 +2288,7 @@ impl<'a> Parser<'a> {
22802288
this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
22812289
})?;
22822290
let span = lo.to(expr.span);
2291+
self.sess.gated_spans.gate(sym::let_chains, span);
22832292
Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span)))
22842293
}
22852294

@@ -2571,13 +2580,15 @@ impl<'a> Parser<'a> {
25712580
pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {
25722581
// Used to check the `let_chains` and `if_let_guard` features mostly by scaning
25732582
// `&&` tokens.
2574-
fn check_let_expr(expr: &Expr) -> bool {
2583+
fn check_let_expr(expr: &Expr) -> (bool, bool) {
25752584
match expr.kind {
25762585
ExprKind::Binary(BinOp { node: BinOpKind::And, .. }, ref lhs, ref rhs) => {
2577-
check_let_expr(lhs) || check_let_expr(rhs)
2586+
let lhs_rslt = check_let_expr(lhs);
2587+
let rhs_rslt = check_let_expr(rhs);
2588+
(lhs_rslt.0 || rhs_rslt.0, false)
25782589
}
2579-
ExprKind::Let(..) => true,
2580-
_ => false,
2590+
ExprKind::Let(..) => (true, true),
2591+
_ => (false, true),
25812592
}
25822593
}
25832594
let attrs = self.parse_outer_attributes()?;
@@ -2592,7 +2603,12 @@ impl<'a> Parser<'a> {
25922603
let guard = if this.eat_keyword(kw::If) {
25932604
let if_span = this.prev_token.span;
25942605
let cond = this.parse_expr_res(Restrictions::ALLOW_LET, None)?;
2595-
if check_let_expr(&cond) {
2606+
let (has_let_expr, does_not_have_bin_op) = check_let_expr(&cond);
2607+
if has_let_expr {
2608+
if does_not_have_bin_op {
2609+
// Remove the last feature gating of a `let` expression since it's stable.
2610+
this.sess.gated_spans.ungate_last(sym::let_chains, cond.span);
2611+
}
25962612
let span = if_span.to(cond.span);
25972613
this.sess.gated_spans.gate(sym::if_let_guard, span);
25982614
}

compiler/rustc_passes/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#![allow(rustc::potential_query_instability)]
88
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
99
#![feature(iter_intersperse)]
10+
#![feature(let_chains)]
1011
#![feature(let_else)]
1112
#![feature(map_try_insert)]
1213
#![feature(min_specialization)]

compiler/rustc_resolve/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#![feature(drain_filter)]
1212
#![feature(if_let_guard)]
1313
#![feature(iter_intersperse)]
14+
#![feature(let_chains)]
1415
#![feature(let_else)]
1516
#![feature(never_type)]
1617
#![recursion_limit = "256"]

compiler/rustc_session/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![feature(if_let_guard)]
2+
#![feature(let_chains)]
23
#![feature(let_else)]
34
#![feature(min_specialization)]
45
#![feature(never_type)]

compiler/rustc_trait_selection/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#![feature(drain_filter)]
1818
#![feature(hash_drain_filter)]
1919
#![cfg_attr(bootstrap, feature(label_break_value))]
20+
#![feature(let_chains)]
2021
#![feature(let_else)]
2122
#![feature(if_let_guard)]
2223
#![feature(never_type)]

compiler/rustc_typeck/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ This API is completely unstable and subject to change.
6565
#![feature(is_sorted)]
6666
#![feature(iter_intersperse)]
6767
#![cfg_attr(bootstrap, feature(label_break_value))]
68+
#![feature(let_chains)]
6869
#![feature(let_else)]
6970
#![feature(min_specialization)]
7071
#![feature(never_type)]

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@
254254
#![feature(intra_doc_pointers)]
255255
#![cfg_attr(bootstrap, feature(label_break_value))]
256256
#![feature(lang_items)]
257+
#![feature(let_chains)]
257258
#![feature(let_else)]
258259
#![feature(linkage)]
259260
#![feature(link_cfg)]

src/librustdoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#![feature(box_patterns)]
99
#![feature(control_flow_enum)]
1010
#![feature(drain_filter)]
11+
#![feature(let_chains)]
1112
#![feature(let_else)]
1213
#![feature(test)]
1314
#![feature(never_type)]

src/test/ui/expr/if/attrs/let-chains-attr.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// check-pass
22

3+
#![feature(let_chains)]
4+
35
#[cfg(FALSE)]
46
fn foo() {
57
#[attr]

src/test/ui/expr/if/bad-if-let-suggestion.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
fn a() {
55
if let x = 1 && i = 2 {}
66
//~^ ERROR cannot find value `i` in this scope
7+
//~| ERROR `let` expressions in this position are unstable
78
//~| ERROR mismatched types
89
//~| ERROR `let` expressions are not supported here
910
}

src/test/ui/expr/if/bad-if-let-suggestion.stderr

+15-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ LL | if let x = 1 && i = 2 {}
1313
| ^ not found in this scope
1414

1515
error[E0425]: cannot find value `i` in this scope
16-
--> $DIR/bad-if-let-suggestion.rs:12:9
16+
--> $DIR/bad-if-let-suggestion.rs:13:9
1717
|
1818
LL | fn a() {
1919
| ------ similarly named function `a` defined here
@@ -22,7 +22,7 @@ LL | if (i + j) = i {}
2222
| ^ help: a function with a similar name exists: `a`
2323

2424
error[E0425]: cannot find value `j` in this scope
25-
--> $DIR/bad-if-let-suggestion.rs:12:13
25+
--> $DIR/bad-if-let-suggestion.rs:13:13
2626
|
2727
LL | fn a() {
2828
| ------ similarly named function `a` defined here
@@ -31,7 +31,7 @@ LL | if (i + j) = i {}
3131
| ^ help: a function with a similar name exists: `a`
3232

3333
error[E0425]: cannot find value `i` in this scope
34-
--> $DIR/bad-if-let-suggestion.rs:12:18
34+
--> $DIR/bad-if-let-suggestion.rs:13:18
3535
|
3636
LL | fn a() {
3737
| ------ similarly named function `a` defined here
@@ -40,21 +40,30 @@ LL | if (i + j) = i {}
4040
| ^ help: a function with a similar name exists: `a`
4141

4242
error[E0425]: cannot find value `x` in this scope
43-
--> $DIR/bad-if-let-suggestion.rs:19:8
43+
--> $DIR/bad-if-let-suggestion.rs:20:8
4444
|
4545
LL | fn a() {
4646
| ------ similarly named function `a` defined here
4747
...
4848
LL | if x[0] = 1 {}
4949
| ^ help: a function with a similar name exists: `a`
5050

51+
error[E0658]: `let` expressions in this position are unstable
52+
--> $DIR/bad-if-let-suggestion.rs:5:8
53+
|
54+
LL | if let x = 1 && i = 2 {}
55+
| ^^^^^^^^^
56+
|
57+
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
58+
= help: add `#![feature(let_chains)]` to the crate attributes to enable
59+
5160
error[E0308]: mismatched types
5261
--> $DIR/bad-if-let-suggestion.rs:5:8
5362
|
5463
LL | if let x = 1 && i = 2 {}
5564
| ^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
5665

57-
error: aborting due to 7 previous errors
66+
error: aborting due to 8 previous errors
5867

59-
Some errors have detailed explanations: E0308, E0425.
68+
Some errors have detailed explanations: E0308, E0425, E0658.
6069
For more information about an error, try `rustc --explain E0308`.

src/test/ui/mir/issue-92893.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
struct Bug<A = [(); (let a = (), 1).1]> {
22
//~^ `let` expressions are not supported here
3+
//~| `let` expressions in this position are unstable [E0658]
34
//~| expected expression, found `let` statement
45
a: A
56
}

0 commit comments

Comments
 (0)