diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index 91f343b8d..ee825b2c4 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 88044a717..fed0deef3 100644
--- a/src/attributes/type_system.md
+++ b/src/attributes/type_system.md
@@ -210,7 +210,6 @@ Non-exhaustive types are always considered inhabited in downstream crates.
[_StructExpression_]: ../expressions/struct-expr.md
[_StructPattern_]: ../patterns.md#struct-patterns
[_TupleStructPattern_]: ../patterns.md#tuple-struct-patterns
-[`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 61e0f62f8..e6adc0b96 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.")
## Const context
[const context]: #const-context
@@ -186,7 +188,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
@@ -203,4 +204,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 7ec6d6fe1..3b2097503 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
@@ -204,11 +205,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]).
> **Notes**:
@@ -473,10 +474,10 @@ variable or field from being dropped automatically.
[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 6de08086d..78e7d3ef5 100644
--- a/src/expressions.md
+++ b/src/expressions.md
@@ -41,7 +41,6 @@ r[expr.syntax]
> | [_UnsafeBlockExpression_]\
> | [_LoopExpression_]\
> | [_IfExpression_]\
-> | [_IfLetExpression_]\
> | [_MatchExpression_]\
> )
@@ -309,13 +308,13 @@ They are never allowed before:
[call expressions]: expressions/call-expr.md
[field]: expressions/field-expr.md
[functional update]: expressions/struct-expr.md#functional-update-syntax
-[`if let`]: expressions/if-expr.md#if-let-expressions
+[`if let`]: expressions/if-expr.md#if-let-patterns
[match]: expressions/match-expr.md
[method-call]: expressions/method-call-expr.md
[paths]: expressions/path-expr.md
[struct]: expressions/struct-expr.md
[tuple expressions]: expressions/tuple-expr.md
-[`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
@@ -362,7 +361,6 @@ They are never allowed before:
[_FieldExpression_]: expressions/field-expr.md
[_GroupedExpression_]: expressions/grouped-expr.md
[_IfExpression_]: expressions/if-expr.md#if-expressions
-[_IfLetExpression_]: expressions/if-expr.md#if-let-expressions
[_IndexExpression_]: expressions/array-expr.md#array-and-slice-indexing-expressions
[_LazyBooleanExpression_]: expressions/operator-expr.md#lazy-boolean-operators
[_LiteralExpression_]: expressions/literal-expr.md
diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md
index 3afebefe5..ad9ed1737 100644
--- a/src/expressions/block-expr.md
+++ b/src/expressions/block-expr.md
@@ -251,7 +251,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.
@@ -278,7 +278,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 e2fbf3a9a..ccf354846 100644
--- a/src/expressions/if-expr.md
+++ b/src/expressions/if-expr.md
@@ -1,35 +1,43 @@
r[expr.if]
-# `if` and `if let` expressions
-
-## `if` expressions
+# `if` expressions
r[expr.if.syntax]
+## Syntax
+
> **Syntax**\
> _IfExpression_ :\
-> `if` [_Expression_]_except struct expression_ [_BlockExpression_]\
-> (`else` (
-> [_BlockExpression_]
-> | _IfExpression_
-> | _IfLetExpression_ ) )\?
+> `if` _IfConditions_ [_BlockExpression_]\
+> (`else` ( [_BlockExpression_] | _IfExpression_ ) )\?
+>
+> _IfConditions_ :\
+> _IfCondition_ ( && _IfCondition_ )*[^if-condition-2024]
+>
+> _IfCondition_ :\
+> [_Expression_]_except struct expression or lazy boolean expression_\
+> | `let` [_Pattern_] `=` [_Scrutinee_]_except struct expression or lazy boolean expression_
+>
+> [^if-condition-2024]: Editions before 2024 only allow a single _IfCondition_.
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.
@@ -44,6 +52,7 @@ if x == 4 {
println!("x is something else");
}
+// `if` can be used as an expression.
let y = if 12 * 15 > 150 {
"Bigger"
} else {
@@ -53,34 +62,17 @@ assert_eq!(y, "Bigger");
```
r[expr.if.let]
-## `if let` expressions
-
-r[expr.if.let.syntax]
-> **Syntax**\
-> _IfLetExpression_ :\
-> `if` `let` [_Pattern_] `=` [_Scrutinee_]_except lazy boolean operator expression_
-> [_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 {
@@ -88,7 +80,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);
}
@@ -98,47 +90,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 {
@@ -152,32 +106,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][_LazyBooleanOperatorExpression_].
-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 `&&`.
-
-```rust,ignore
-// Before...
-if let PAT = EXPR && EXPR { .. }
+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.
-// After...
-if let PAT = ( EXPR && EXPR ) { .. }
+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.
-// Before...
-if let PAT = EXPR || EXPR { .. }
+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:
-// After...
-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");
+ }
+}
```
+The above is equivalent to the following without using chains of conditions:
+
+```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:
+
+```rust
+# let foo = Some(123);
+# let condition1 = true;
+# let condition2 = false;
+// Parentheses are required here.
+if let Some(x) = foo && (condition1 || condition2) { /*...*/ }
+```
+
+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
-[_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
+[`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 c60453143..cfcf44949 100644
--- a/src/expressions/loop-expr.md
+++ b/src/expressions/loop-expr.md
@@ -7,7 +7,6 @@ r[expr.loop.syntax]
> [_LoopLabel_]? (\
> [_InfiniteLoopExpression_]\
> | [_PredicateLoopExpression_]\
-> | [_PredicatePatternLoopExpression_]\
> | [_IteratorLoopExpression_]\
> | [_LabelBlockExpression_]\
> )
@@ -15,21 +14,19 @@ r[expr.loop.syntax]
[_LoopLabel_]: #loop-labels
[_InfiniteLoopExpression_]: #infinite-loops
[_PredicateLoopExpression_]: #predicate-loops
-[_PredicatePatternLoopExpression_]: #predicate-pattern-loops
[_IteratorLoopExpression_]: #iterator-loops
[_LabelBlockExpression_]: #labelled-block-expressions
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).
@@ -58,17 +55,38 @@ A `loop` expression containing associated [`break` expression(s)](#break-express
r[expr.loop.while]
## Predicate loops
-r[expr.loop.while.syntax]
> **Syntax**\
-> _PredicateLoopExpression_ :\
-> `while` [_Expression_]_except struct expression_ [_BlockExpression_]
+> [_PredicateLoopExpression_] :\
+> `while` _WhileConditions_ [_BlockExpression_]
+>
+> _WhileConditions_ :\
+> _WhileCondition_ ( && _WhileCondition_ )*
+>
+> _WhileCondition_ :\
+> [_Expression_]_except struct expression_\
+> | `let` [_Pattern_] `=` [_Scrutinee_]
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:
@@ -82,20 +100,11 @@ while i < 10 {
```
r[expr.loop.while.let]
-## Predicate pattern loops
-
-r[expr.loop.while.let.syntax]
-> **Syntax**\
-> [_PredicatePatternLoopExpression_] :\
-> `while` `let` [_Pattern_] `=` [_Scrutinee_]_except lazy boolean operator expression_
-> [_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];
@@ -144,8 +153,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][_LazyBooleanOperatorExpression_].
+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
@@ -336,7 +365,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.
@@ -375,11 +404,12 @@ In the case a `loop` has an associated `break`, it is not considered diverging,
[LIFETIME_OR_LABEL]: ../tokens.md#lifetimes-and-loop-labels
[_BlockExpression_]: block-expr.md
[_Expression_]: ../expressions.md
+[_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators
[_Pattern_]: ../patterns.md
[_Scrutinee_]: match-expr.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
-[_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators
-[`if let` expressions]: if-expr.md#if-let-expressions
diff --git a/src/expressions/struct-expr.md b/src/expressions/struct-expr.md
index cffadef57..d4ac0c2d6 100644
--- a/src/expressions/struct-expr.md
+++ b/src/expressions/struct-expr.md
@@ -149,7 +149,7 @@ let b = Gamma{}; // Exact same value as `a`.
[_PathInExpression_]: ../paths.md#paths-in-expressions
[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/patterns.md b/src/patterns.md
index dcb8f33fe..9f7d263fc 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 317a437ce..f678998c8 100644
--- a/src/tokens.md
+++ b/src/tokens.md
@@ -942,7 +942,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
@@ -973,4 +973,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