From 5cfeea6789211641f82622187528ca7f5d80235e Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 23 Feb 2025 18:19:49 +0100 Subject: [PATCH] Document let chains again --- src/SUMMARY.md | 2 +- src/attributes/type_system.md | 1 - src/const_eval.md | 8 +- src/destructors.md | 15 +-- src/expressions.md | 5 +- src/expressions/block-expr.md | 3 +- src/expressions/if-expr.md | 172 ++++++++++++++++----------------- src/expressions/loop-expr.md | 85 +++++++++++----- src/expressions/struct-expr.md | 2 +- src/names.md | 4 +- src/names/namespaces.md | 4 +- src/names/scopes.md | 10 +- src/patterns.md | 2 +- src/tokens.md | 4 +- 14 files changed, 173 insertions(+), 144 deletions(-) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 980a61ef0..cbee8c018 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -63,7 +63,7 @@ - [Closure expressions](expressions/closure-expr.md) - [Loop expressions](expressions/loop-expr.md) - [Range expressions](expressions/range-expr.md) - - [If and if let expressions](expressions/if-expr.md) + - [If expressions](expressions/if-expr.md) - [Match expressions](expressions/match-expr.md) - [Return expressions](expressions/return-expr.md) - [Await expressions](expressions/await-expr.md) diff --git a/src/attributes/type_system.md b/src/attributes/type_system.md index a6f05d788..0a3d4f15f 100644 --- a/src/attributes/type_system.md +++ b/src/attributes/type_system.md @@ -206,7 +206,6 @@ let _ = EnumWithNonExhaustiveVariants::First as u8; Non-exhaustive types are always considered inhabited in downstream crates. -[`if let`]: ../expressions/if-expr.md#if-let-expressions [`match`]: ../expressions/match-expr.md [attributes]: ../attributes.md [enum]: ../items/enumerations.md diff --git a/src/const_eval.md b/src/const_eval.md index 07f704512..8475ef962 100644 --- a/src/const_eval.md +++ b/src/const_eval.md @@ -102,10 +102,12 @@ r[const-eval.const-expr.const-fn] * Calls of [const functions] and const methods. r[const-eval.const-expr.loop] -* [loop], [while] and [`while let`] expressions. +* [loop] and [while] expressions. r[const-eval.const-expr.if-match] -* [if], [`if let`] and [match] expressions. +* [if] and [match] expressions. + +expressions.") r[const-eval.const-context] ## Const context @@ -185,7 +187,6 @@ of whether you are building on a `64` bit or a `32` bit system. [grouped]: expressions/grouped-expr.md [interior mutability]: interior-mutability.md [if]: expressions/if-expr.md#if-expressions -[`if let`]: expressions/if-expr.md#if-let-expressions [lazy boolean]: expressions/operator-expr.md#lazy-boolean-operators [let statements]: statements.md#let-statements [literals]: expressions/literal-expr.md @@ -202,4 +203,3 @@ of whether you are building on a `64` bit or a `32` bit system. [struct]: expressions/struct-expr.md [tuple expressions]: expressions/tuple-expr.md [while]: expressions/loop-expr.md#predicate-loops -[`while let`]: expressions/loop-expr.md#predicate-pattern-loops diff --git a/src/destructors.md b/src/destructors.md index 2f4711815..dbf1dcd1d 100644 --- a/src/destructors.md +++ b/src/destructors.md @@ -67,8 +67,9 @@ leaves a drop scope all variables associated to that scope are dropped in reverse order of declaration (for variables) or creation (for temporaries). r[destructors.scope.desugaring] -Drop scopes are determined after replacing [`for`], [`if let`], and -[`while let`] expressions with the equivalent expressions using [`match`]. +Drop scopes can be determined by replacing [`for`], [`if`], and [`while`] +expressions with equivalent expressions using [`match`], [`loop`] and +`break`. r[destructors.scope.operators] Overloaded operators are not distinguished from built-in operators and [binding @@ -203,11 +204,11 @@ smallest scope that contains the expression and is one of the following: * A statement. * The body of an [`if`], [`while`] or [`loop`] expression. * The `else` block of an `if` expression. -* The condition expression of an `if` or `while` expression, or a `match` - guard. +* The non-pattern matching condition expression of an `if` or `while` expression, + or a `match` guard. * The body expression for a match arm. * Each operand of a [lazy boolean expression]. -* The pattern-matching condition and consequent body of [`if let`] ([destructors.scope.temporary.edition2024]). +* The pattern-matching condition(s) and consequent body of [`if`] ([destructors.scope.temporary.edition2024]). * The entirety of the tail expression of a block ([destructors.scope.temporary.edition2024]). > [!NOTE] @@ -479,10 +480,10 @@ There is one additional case to be aware of: when a panic reaches a [non-unwindi [tuple indexing expression]: expressions/tuple-expr.md#tuple-indexing-expressions [`for`]: expressions/loop-expr.md#iterator-loops -[`if let`]: expressions/if-expr.md#if-let-expressions +[`if let`]: expressions/if-expr.md#if-let-patterns [`if`]: expressions/if-expr.md#if-expressions [`let` statement]: statements.md#let-statements [`loop`]: expressions/loop-expr.md#infinite-loops [`match`]: expressions/match-expr.md -[`while let`]: expressions/loop-expr.md#predicate-pattern-loops +[`while let`]: expressions/loop-expr.md#while-let-patterns [`while`]: expressions/loop-expr.md#predicate-loops diff --git a/src/expressions.md b/src/expressions.md index 562ed2bfd..e7d277abc 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -41,7 +41,6 @@ ExpressionWithBlock -> | UnsafeBlockExpression | LoopExpression | IfExpression - | IfLetExpression | MatchExpression ) ``` @@ -311,9 +310,9 @@ They are never allowed before: [`Copy`]: special-types-and-traits.md#copy [`Drop`]: special-types-and-traits.md#drop -[`if let`]: expressions/if-expr.md#if-let-expressions +[`if let`]: expressions/if-expr.md#if-let-patterns [`Sized`]: special-types-and-traits.md#sized -[`while let`]: expressions/loop-expr.md#predicate-pattern-loops +[`while let`]: expressions/loop-expr.md#while-let-patterns [array expressions]: expressions/array-expr.md [array indexing]: expressions/array-expr.md#array-and-slice-indexing-expressions [assign]: expressions/operator-expr.md#assignment-expressions diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md index 0a63e7272..da0f93b36 100644 --- a/src/expressions/block-expr.md +++ b/src/expressions/block-expr.md @@ -258,7 +258,7 @@ r[expr.block.attributes.inner-attributes] [Inner attributes] are allowed directly after the opening brace of a block expression in the following situations: * [Function] and [method] bodies. -* Loop bodies ([`loop`], [`while`], [`while let`], and [`for`]). +* Loop bodies ([`loop`], [`while`], and [`for`]). * Block expressions used as a [statement]. * Block expressions as elements of [array expressions], [tuple expressions], [call expressions], and tuple-style [struct] expressions. @@ -282,7 +282,6 @@ fn is_unix_platform() -> bool { [`for`]: loop-expr.md#iterator-loops [`loop`]: loop-expr.md#infinite-loops [`unsafe` blocks]: ../unsafe-keyword.md#unsafe-blocks-unsafe- -[`while let`]: loop-expr.md#predicate-pattern-loops [`while`]: loop-expr.md#predicate-loops [array expressions]: array-expr.md [call expressions]: call-expr.md diff --git a/src/expressions/if-expr.md b/src/expressions/if-expr.md index 66aa1b0e4..315938f17 100644 --- a/src/expressions/if-expr.md +++ b/src/expressions/if-expr.md @@ -1,34 +1,40 @@ r[expr.if] -# `if` and `if let` expressions - -## `if` expressions +# `if` expressions r[expr.if.syntax] ```grammar,expressions IfExpression -> - `if` Expression _except [StructExprStruct]_ BlockExpression - (`else` ( BlockExpression | IfExpression | IfLetExpression ) )? + `if` IfConditions BlockExpression + (`else` ( BlockExpression | IfExpression ) )? + +IfConditions -> IfCondition ( `&&` IfCondition )* + +IfCondition -> + Expression _except [StructExprStruct]_ + | `let` Pattern `=` Scrutinee _except [LazyBooleanExpression]_ ``` r[expr.if.intro] -An `if` expression is a conditional branch in program control. -The syntax of an `if` expression is a condition operand, followed by a consequent block, any number of `else if` conditions and blocks, and an optional trailing `else` block. +The syntax of an `if` expression is a sequence of one or more condition operands separated by `&&`, +followed by a consequent block, any number of `else if` conditions and blocks, and an optional trailing `else` block. -r[expr.if.condition-bool] -The condition operands must have the [boolean type]. +r[expr.if.condition] +Condition operands must be either an [_Expression_] with a [boolean type] or a conditional `let` match. r[expr.if.condition-true] -If a condition operand evaluates to `true`, the consequent block is executed and any subsequent `else if` or `else` block is skipped. +If all of the condition operands evaluate to `true` and all of the `let` patterns successfully match their [scrutinee]s, +the consequent block is executed and any subsequent `else if` or `else` block is skipped. r[expr.if.else-if] -If a condition operand evaluates to `false`, the consequent block is skipped and any subsequent `else if` condition is evaluated. +If any condition operand evaluates to `false` or any `let` pattern does not match its scrutinee, +the consequent block is skipped and any subsequent `else if` condition is evaluated. r[expr.if.else] If all `if` and `else if` conditions evaluate to `false` then any `else` block is executed. r[expr.if.result] -An if expression evaluates to the same value as the executed block, or `()` if no block is evaluated. +An `if` expression evaluates to the same value as the executed block, or `()` if no block is evaluated. r[expr.if.type] An `if` expression must have the same type in all situations. @@ -43,6 +49,7 @@ if x == 4 { println!("x is something else"); } +// `if` can be used as an expression. let y = if 12 * 15 > 150 { "Bigger" } else { @@ -52,31 +59,17 @@ assert_eq!(y, "Bigger"); ``` r[expr.if.let] -## `if let` expressions - -r[expr.if.let.syntax] -```grammar,expressions -IfLetExpression -> - `if` `let` Pattern `=` Scrutinee _except [LazyBooleanExpression]_ BlockExpression - (`else` ( BlockExpression | IfExpression | IfLetExpression ) )? -``` +## `if let` patterns r[expr.if.let.intro] -An `if let` expression is semantically similar to an `if` expression but in place of a condition operand it expects the keyword `let` followed by a pattern, an `=` and a [scrutinee] operand. - -r[expr.if.let.pattern] -If the value of the scrutinee matches the pattern, the corresponding block will execute. +`let` patterns in an `if` condition allow binding new variables into scope when the pattern matches successfully. -r[expr.if.let.else] -Otherwise, flow proceeds to the following `else` block if it exists. - -r[expr.if.let.result] -Like `if` expressions, `if let` expressions have a value determined by the block that is evaluated. +The following examples illustrate bindings using `let` patterns: ```rust let dish = ("Ham", "Eggs"); -// this body will be skipped because the pattern is refuted +// This body will be skipped because the pattern is refuted. if let ("Bacon", b) = dish { println!("Bacon is served with {}", b); } else { @@ -84,7 +77,7 @@ if let ("Bacon", b) = dish { println!("No bacon will be served"); } -// this body will execute +// This body will execute. if let ("Ham", b) = dish { println!("Ham is served with {}", b); } @@ -94,47 +87,9 @@ if let _ = 5 { } ``` -r[expr.if.let.else-if] -`if` and `if let` expressions can be intermixed: - -```rust -let x = Some(3); -let a = if let Some(1) = x { - 1 -} else if x == Some(2) { - 2 -} else if let Some(y) = x { - y -} else { - -1 -}; -assert_eq!(a, 3); -``` - -r[expr.if.let.desugaring] -An `if let` expression is equivalent to a [`match` expression] as follows: - - -```rust,ignore -if let PATS = EXPR { - /* body */ -} else { - /*else */ -} -``` - -is equivalent to - - -```rust,ignore -match EXPR { - PATS => { /* body */ }, - _ => { /* else */ }, // () if there is no else -} -``` - r[expr.if.let.or-pattern] -Multiple patterns may be specified with the `|` operator. This has the same semantics as with `|` in `match` expressions: +Multiple patterns may be specified with the `|` operator. +This has the same semantics as with `|` in [`match` expressions]: ```rust enum E { @@ -148,27 +103,70 @@ if let E::X(n) | E::Y(n) = v { } ``` -r[expr.if.let.lazy-bool] -The expression cannot be a [lazy boolean operator expression][expr.bool-logic]. -Use of a lazy boolean operator is ambiguous with a planned feature change of the language (the implementation of if-let chains - see [eRFC 2947][_eRFCIfLetChain_]). -When lazy boolean operator expression is desired, this can be achieved by using parenthesis as below: +r[expr.if.chains] +## Chains of conditions + +r[expr.if.chains.intro] +Multiple condition operands can be separated with `&&`. + +r[expr.if.chains.order] +Similar to a `&&` [_LazyBooleanOperatorExpression_], each operand is evaluated from left-to-right until an operand evaluates as `false` or a `let` match fails, +in which case the subsequent operands are not evaluated. + +r[expr.if.chains.bindings] +The bindings of each pattern are put into scope to be available for the next condition operand and the consequent block. + +The following is an example of chaining multiple expressions, mixing `let` bindings and boolean expressions, and with expressions able to reference pattern bindings from previous expressions: - -```rust,ignore -// Before... -if let PAT = EXPR && EXPR { .. } +```rust +fn single() { + let outer_opt = Some(Some(1i32)); + + if let Some(inner_opt) = outer_opt + && let Some(number) = inner_opt + && number == 1 + { + println!("Peek a boo"); + } +} +``` -// After... -if let PAT = ( EXPR && EXPR ) { .. } +The above is equivalent to the following without using chains of conditions: -// Before... -if let PAT = EXPR || EXPR { .. } +```rust +fn nested() { + let outer_opt = Some(Some(1i32)); + + if let Some(inner_opt) = outer_opt { + if let Some(number) = inner_opt { + if number == 1 { + println!("Peek a boo"); + } + } + } +} +``` + +r[expr.if.chains.or] +If any condition operand is a `let` pattern, then none of the condition operands can be a `||` [lazy boolean operator expression][_LazyBooleanOperatorExpression_] due to ambiguity and precedence with the `let` scrutinee. +If a `||` expression is needed, then parentheses can be used. For example: -// After... -if let PAT = ( EXPR || EXPR ) { .. } +```rust +# let foo = Some(123); +# let condition1 = true; +# let condition2 = false; +// Parentheses are required here. +if let Some(x) = foo && (condition1 || condition2) { /*...*/ } ``` -[_eRFCIfLetChain_]: https://github.com/rust-lang/rfcs/blob/master/text/2497-if-let-chains.md#rollout-plan-and-transitioning-to-rust-2018 -[`match` expression]: match-expr.md +r[expr.if.edition2024] +> **Edition differences**: Before the 2024 edition, let chains are not supported and only a single _IfCondition_ is allowed in an `if` expression. + +[_BlockExpression_]: block-expr.md +[_Expression_]: ../expressions.md +[_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators +[_Pattern_]: ../patterns.md +[_Scrutinee_]: match-expr.md +[`match` expressions]: match-expr.md [boolean type]: ../types/boolean.md [scrutinee]: ../glossary.md#scrutinee diff --git a/src/expressions/loop-expr.md b/src/expressions/loop-expr.md index c9bb452a4..b036405af 100644 --- a/src/expressions/loop-expr.md +++ b/src/expressions/loop-expr.md @@ -7,23 +7,21 @@ LoopExpression -> LoopLabel? ( InfiniteLoopExpression | PredicateLoopExpression - | PredicatePatternLoopExpression | IteratorLoopExpression | LabelBlockExpression ) ``` r[expr.loop.intro] -Rust supports five loop expressions: +Rust supports four loop expressions: * A [`loop` expression](#infinite-loops) denotes an infinite loop. * A [`while` expression](#predicate-loops) loops until a predicate is false. -* A [`while let` expression](#predicate-pattern-loops) tests a pattern. * A [`for` expression](#iterator-loops) extracts values from an iterator, looping until the iterator is empty. * A [labelled block expression](#labelled-block-expressions) runs a loop exactly once, but allows exiting the loop early with `break`. r[expr.loop.break-label] -All five types of loop support [`break` expressions](#break-expressions), and [labels](#loop-labels). +All four types of loop support [`break` expressions](#break-expressions), and [labels](#loop-labels). r[expr.loop.continue-label] All except labelled block expressions support [`continue` expressions](#continue-expressions). @@ -52,18 +50,39 @@ A `loop` expression containing associated [`break` expression(s)](#break-express r[expr.loop.while] ## Predicate loops -r[expr.loop.while.syntax] +r[expr.loop.while.grammar] ```grammar,expressions -PredicateLoopExpression -> `while` Expression _except [StructExprStruct]_ BlockExpression +PredicateLoopExpression -> `while` WhileConditions BlockExpression + +WhileConditions -> WhileCondition ( `&&` WhileCondition )* + +WhileCondition -> + Expression _except [StructExprStruct]_ + | `let` Pattern `=` Scrutinee _except [LazyBooleanExpression]_ ``` r[expr.loop.while.intro] -A `while` loop begins by evaluating the [boolean] loop conditional operand. +A `while` loop expression allows repeating the evaluation of a block while a set of conditions remain true. + +r[expr.loop.while.syntax] +The syntax of a `while` expression is a sequence of one or more condition operands separated by `&&`, +followed by a [_BlockExpression_]. r[expr.loop.while.condition] -If the loop conditional operand evaluates to `true`, the loop body block executes, then control returns to the loop conditional operand. -If the loop conditional expression evaluates to `false`, the `while` expression completes. +Condition operands must be either an [_Expression_] with a [boolean type] or a conditional `let` match. +If all of the condition operands evaluate to `true` and all of the `let` patterns successfully match their [scrutinee]s, +then the loop body block executes. + +r[expr.loop.while.repeat] +After the loop body successfully executes, the condition operands are re-evaluated to determine if the body should be executed again. + +r[expr.loop.while.exit] +If any condition operand evaluates to `false` or any `let` pattern does not match its scrutinee, +the body is not executed and execution continues after the `while` expression. + +r[expr.loop.while.eval] +A `while` expression evaluates to `()`. An example: @@ -77,20 +96,11 @@ while i < 10 { ``` r[expr.loop.while.let] -## Predicate pattern loops - -r[expr.loop.while.let.syntax] -```grammar,expressions -PredicatePatternLoopExpression -> - `while` `let` Pattern `=` Scrutinee _except [LazyBooleanExpression]_ BlockExpression -``` +### `while let` patterns r[expr.loop.while.let.intro] -A `while let` loop is semantically similar to a `while` loop but in place of a condition expression it expects the keyword `let` followed by a pattern, an `=`, a [scrutinee] expression and a block expression. - -r[expr.loop.while.let.condition] -If the value of the scrutinee matches the pattern, the loop body block executes then control returns to the pattern matching statement. -Otherwise, the while expression completes. +`let` patterns in a `while` condition allow binding new variables into scope when the pattern matches successfully. +The following examples illustrate bindings using `let` patterns: ```rust let mut x = vec![1, 2, 3]; @@ -139,8 +149,28 @@ while let Some(v @ 1) | Some(v @ 2) = vals.pop() { } ``` -r[expr.loop.while.let.lazy-bool] -As is the case in [`if let` expressions], the scrutinee cannot be a [lazy boolean operator expression][expr.bool-logic]. +r[expr.loop.while.chains] +### `while` condition chains + +r[expr.loop.while.chains.intro] +Multiple condition operands can be separated with `&&`. +These have the same semantics and restrictions as [`if` condition chains]. + +The following is an example of chaining multiple expressions, mixing `let` bindings and boolean expressions, and with expressions able to reference pattern bindings from previous expressions: + +```rust +fn main() { + let outer_opt = Some(Some(1i32)); + + while let Some(inner_opt) = outer_opt + && let Some(number) = inner_opt + && number == 1 + { + println!("Peek a boo"); + break; + } +} +``` r[expr.loop.for] ## Iterator loops @@ -333,7 +363,7 @@ r[expr.loop.continue.intro] When `continue` is encountered, the current iteration of the associated loop body is immediately terminated, returning control to the loop *head*. r[expr.loop.continue.while] -In the case of a `while` loop, the head is the conditional expression controlling the loop. +In the case of a `while` loop, the head is the conditional operands controlling the loop. r[expr.loop.continue.for] In the case of a `for` loop, the head is the call-expression controlling the loop. @@ -369,8 +399,11 @@ r[expr.loop.break-value.loop] In the case a `loop` has an associated `break`, it is not considered diverging, and the `loop` must have a type compatible with each `break` expression. `break` without an expression is considered identical to `break` with expression `()`. +[_BlockExpression_]: block-expr.md +[_Expression_]: ../expressions.md +[`if` condition chains]: if-expr.md#chains-of-conditions +[`if` expressions]: if-expr.md [`match` expression]: match-expr.md -[boolean]: ../types/boolean.md +[boolean type]: ../types/boolean.md [scrutinee]: ../glossary.md#scrutinee [temporary values]: ../expressions.md#temporaries -[`if let` expressions]: if-expr.md#if-let-expressions diff --git a/src/expressions/struct-expr.md b/src/expressions/struct-expr.md index 79a3a2e20..deb0bd62d 100644 --- a/src/expressions/struct-expr.md +++ b/src/expressions/struct-expr.md @@ -144,7 +144,7 @@ let b = Gamma{}; // Exact same value as `a`. [call expression]: call-expr.md [enum variant]: ../items/enumerations.md -[if let]: if-expr.md#if-let-expressions +[if let]: if-expr.md#if-let-patterns [if]: if-expr.md#if-expressions [loop]: loop-expr.md [match]: match-expr.md diff --git a/src/names.md b/src/names.md index 92d2cd82c..b9af0e535 100644 --- a/src/names.md +++ b/src/names.md @@ -135,13 +135,13 @@ to with certain [path qualifiers] or aliases. [*visibility*]: visibility-and-privacy.md [`'static`]: keywords.md#weak-keywords [`for`]: expressions/loop-expr.md#iterator-loops -[`if let`]: expressions/if-expr.md#if-let-expressions +[`if let`]: expressions/if-expr.md#if-let-patterns [`let` statement]: statements.md#let-statements [`macro_export` attribute]: macros-by-example.md#path-based-scope [`macro_rules` declarations]: macros-by-example.md [`macro_use` attribute]: macros-by-example.md#the-macro_use-attribute [`match`]: expressions/match-expr.md -[`while let`]: expressions/loop-expr.md#predicate-pattern-loops +[`while let`]: expressions/loop-expr.md#while-let-patterns [associated items]: items/associated-items.md [attributes]: attributes.md [Boolean type]: types/boolean.md diff --git a/src/names/namespaces.md b/src/names/namespaces.md index afe48a2e5..feb0e9771 100644 --- a/src/names/namespaces.md +++ b/src/names/namespaces.md @@ -123,14 +123,14 @@ It is still an error for a [`use` import] to shadow another macro, regardless of [`cfg` attribute]: ../conditional-compilation.md#the-cfg-attribute [`cfg` macro]: ../conditional-compilation.md#the-cfg-macro [`for`]: ../expressions/loop-expr.md#iterator-loops -[`if let`]: ../expressions/if-expr.md#if-let-expressions +[`if let`]: ../expressions/if-expr.md#if-let-patterns [`let`]: ../statements.md#let-statements [`macro_rules` declarations]: ../macros-by-example.md [`match`]: ../expressions/match-expr.md [`Self` constructors]: ../paths.md#self-1 [`Self` type]: ../paths.md#self-1 [`use` import]: ../items/use-declarations.md -[`while let`]: ../expressions/loop-expr.md#predicate-pattern-loops +[`while let`]: ../expressions/loop-expr.md#while-let-patterns [Associated const declarations]: ../items/associated-items.md#associated-constants [Associated function declarations]: ../items/associated-items.md#associated-functions-and-methods [Associated type declarations]: ../items/associated-items.md#associated-types diff --git a/src/names/scopes.md b/src/names/scopes.md index cfc5ffd30..0a7240512 100644 --- a/src/names/scopes.md +++ b/src/names/scopes.md @@ -49,9 +49,9 @@ r[names.scopes.pattern-bindings.parameter] r[names.scopes.pattern-bindings.closure] * [Closure parameter] bindings are within the closure body. r[names.scopes.pattern-bindings.loop] -* [`for`] and [`while let`] bindings are within the loop body. -r[names.scopes.pattern-bindings.if-let] -* [`if let`] bindings are within the consequent block. +* [`for`] bindings are within the loop body. +r[names.scopes.pattern-bindings.let-chains] +* [`if let`] and [`while let`] bindings are valid in the following conditions as well as the consequent block. r[names.scopes.pattern-bindings.match-arm] * [`match` arms] bindings are within the [match guard] and the match arm expression. @@ -340,14 +340,14 @@ impl ImplExample { [`derive` attribute]: ../attributes/derive.md [`for` loop]: ../expressions/loop-expr.md#iterator-loops [`for`]: ../expressions/loop-expr.md#iterator-loops -[`if let`]: ../expressions/if-expr.md#if-let-expressions +[`if let`]: ../expressions/if-expr.md#if-let-patterns +[`while let`]: ../expressions/loop-expr.md#while-let-patterns [`let` statement]: ../statements.md#let-statements [`macro_export`]: ../macros-by-example.md#path-based-scope [`macro_use` prelude]: preludes.md#macro_use-prelude [`macro_use`]: ../macros-by-example.md#the-macro_use-attribute [`match` arms]: ../expressions/match-expr.md [`Self`]: ../paths.md#self-1 -[`while let`]: ../expressions/loop-expr.md#predicate-pattern-loops [Associated consts]: ../items/associated-items.md#associated-constants [associated items]: ../items/associated-items.md [Asterisk glob imports]: ../items/use-declarations.md diff --git a/src/patterns.md b/src/patterns.md index cda82076e..2d9ddb5ac 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -79,7 +79,7 @@ r[patterns.if-let] * [`if let` expressions](expressions/if-expr.md) r[patterns.while-let] -* [`while let` expressions](expressions/loop-expr.md#predicate-pattern-loops) +* [`while let` expressions](expressions/loop-expr.md#while-let-patterns) r[patterns.for] * [`for` expressions](expressions/loop-expr.md#iterator-loops) diff --git a/src/tokens.md b/src/tokens.md index 7dffe9f51..294753e69 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -1049,7 +1049,7 @@ r[lex.token.reserved-guards.edition2024] [functions]: items/functions.md [generics]: items/generics.md [identifier]: identifiers.md -[if let]: expressions/if-expr.md#if-let-expressions +[if let]: expressions/if-expr.md#if-let-patterns [Integer literal expressions]: expressions/literal-expr.md#integer-literal-expressions [keywords]: keywords.md [lazy-bool]: expressions/operator-expr.md#lazy-boolean-operators @@ -1080,4 +1080,4 @@ r[lex.token.reserved-guards.edition2024] [unary minus operator]: expressions/operator-expr.md#negation-operators [use declarations]: items/use-declarations.md [use wildcards]: items/use-declarations.md -[while let]: expressions/loop-expr.md#predicate-pattern-loops +[while let]: expressions/loop-expr.md#while-let-patterns