diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index 82d70d043..6a8f72475 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -62,7 +62,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 729069d26..d15836fb0 100644
--- a/src/attributes/type_system.md
+++ b/src/attributes/type_system.md
@@ -133,7 +133,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 c0560376c..d735a20ec 100644
--- a/src/const_eval.md
+++ b/src/const_eval.md
@@ -45,8 +45,8 @@ to be run.
   * pointer to address casts and
   * function pointer to address casts.
 * Calls of [const functions] and const methods.
-* [loop], [while] and [`while let`] expressions.
-* [if], [`if let`] and [match] expressions.
+* [loop] and [while] expressions.
+* [if] and [match] expressions.
 
 ## Const context
 
@@ -121,7 +121,6 @@ Conversely, the following are possible in a const function, but not in a const c
 [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
@@ -138,4 +137,3 @@ Conversely, the following are possible in a const function, but not in a const c
 [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 6d616b3e7..083ed86eb 100644
--- a/src/destructors.md
+++ b/src/destructors.md
@@ -388,12 +388,12 @@ variable or field from being dropped automatically.
 [tuple expression]: expressions/tuple-expr.md#tuple-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
 
 [`<T as std::ops::Drop>::drop`]: ../std/ops/trait.Drop.html#tymethod.drop
diff --git a/src/expressions.md b/src/expressions.md
index 32ee658ff..5b6525fec 100644
--- a/src/expressions.md
+++ b/src/expressions.md
@@ -38,7 +38,6 @@
 > &nbsp;&nbsp; &nbsp;&nbsp; | [_UnsafeBlockExpression_]\
 > &nbsp;&nbsp; &nbsp;&nbsp; | [_LoopExpression_]\
 > &nbsp;&nbsp; &nbsp;&nbsp; | [_IfExpression_]\
-> &nbsp;&nbsp; &nbsp;&nbsp; | [_IfLetExpression_]\
 > &nbsp;&nbsp; &nbsp;&nbsp; | [_MatchExpression_]\
 > &nbsp;&nbsp; )
 
@@ -295,13 +294,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
@@ -348,7 +347,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 a68b27e56..01e6ef95c 100644
--- a/src/expressions/block-expr.md
+++ b/src/expressions/block-expr.md
@@ -145,7 +145,7 @@ let a = unsafe { an_unsafe_fn() };
 [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.
@@ -172,7 +172,6 @@ fn is_unix_platform() -> bool {
 [`loop`]: loop-expr.md#infinite-loops
 [`std::ops::Fn`]: ../../std/ops/trait.Fn.html
 [`std::future::Future`]: ../../std/future/trait.Future.html
-[`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 591437fc9..9de65df87 100644
--- a/src/expressions/if-expr.md
+++ b/src/expressions/if-expr.md
@@ -1,22 +1,31 @@
-# `if` and `if let` expressions
+# `if` expressions
 
-## `if` expressions
+## Syntax
 
 > **<sup>Syntax</sup>**\
 > _IfExpression_ :\
-> &nbsp;&nbsp; `if` [_Expression_]<sub>_except struct expression_</sub> [_BlockExpression_]\
-> &nbsp;&nbsp; (`else` (
->   [_BlockExpression_]
-> | _IfExpression_
-> | _IfLetExpression_ ) )<sup>\?</sup>
+> &nbsp;&nbsp; `if` _IfConditions_ [_BlockExpression_]\
+> &nbsp;&nbsp; (`else` ( [_BlockExpression_] | _IfExpression_ ) )<sup>\?</sup>
+>
+> _IfConditions_ :\
+> &nbsp;&nbsp; _IfCondition_ ( && _IfCondition_ )*
+>
+> _IfCondition_ :\
+> &nbsp;&nbsp; &nbsp;&nbsp; [_Expression_]<sub>_except struct expression_</sub>\
+> &nbsp;&nbsp; | `let` [_Pattern_] `=` [_Scrutinee_]
 
 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 condition operands must have the [boolean type].
-If a condition operand evaluates to `true`, the consequent block is executed and any subsequent `else if` or `else` block is skipped.
-If a condition operand evaluates to `false`, the consequent block is skipped and any subsequent `else if` condition is evaluated.
+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.
+
+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,
+the consequent block is executed and any subsequent `else if` or `else` block is skipped.
+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.
 If all `if` and `else if` conditions evaluate to `false` then any `else` block is executed.
-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.
 An `if` expression must have the same type in all situations.
 
 ```rust
@@ -29,6 +38,7 @@ if x == 4 {
     println!("x is something else");
 }
 
+// `if` can be used as an expression.
 let y = if 12 * 15 > 150 {
     "Bigger"
 } else {
@@ -37,26 +47,15 @@ let y = if 12 * 15 > 150 {
 assert_eq!(y, "Bigger");
 ```
 
-## `if let` expressions
+## `if let` patterns
 
-> **<sup>Syntax</sup>**\
-> _IfLetExpression_ :\
-> &nbsp;&nbsp; `if` `let` [_Pattern_] `=` [_Scrutinee_]<sub>_except lazy boolean operator expression_</sub>
->              [_BlockExpression_]\
-> &nbsp;&nbsp; (`else` (
->   [_BlockExpression_]
-> | _IfExpression_
-> | _IfLetExpression_ ) )<sup>\?</sup>
-
-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.
-If the value of the scrutinee matches the pattern, the corresponding block will execute.
-Otherwise, flow proceeds to the following `else` block if it exists.
-Like `if` expressions, `if let` expressions have a value determined by the block that is evaluated.
+`let` patterns in an `if` condition allow binding new variables into scope when the pattern matches successfully.
+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 {
@@ -64,7 +63,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);
 }
@@ -74,44 +73,8 @@ if let _ = 5 {
 }
 ```
 
-`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);
-```
-
-An `if let` expression is equivalent to a [`match` expression] as follows:
-
-<!-- ignore: expansion example -->
-```rust,ignore
-if let PATS = EXPR {
-    /* body */
-} else {
-    /*else */
-}
-```
-
-is equivalent to
-
-<!-- ignore: expansion example -->
-```rust,ignore
-match EXPR {
-    PATS => { /* body */ },
-    _ => { /* else */ },    // () if there is no else
-}
-```
-
-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 {
@@ -125,31 +88,62 @@ if let E::X(n) | E::Y(n) = v {
 }
 ```
 
-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:
+## Chains of conditions
+
+Multiple condition operands can be separated with `&&`.
+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.
+
+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
+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");
+    }
+}
+```
 
-<!-- ignore: psuedo code -->
-```rust,ignore
-// Before...
-if let PAT = EXPR && EXPR { .. }
+The above is equivalent to the following without using chains of conditions:
 
-// After...
-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");
+            }
+        }
+    }
+}
+```
 
-// Before...
-if let PAT = EXPR || EXPR { .. }
+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) { /*...*/ }
 ```
 
+
 [_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 308f3e346..d9458d56f 100644
--- a/src/expressions/loop-expr.md
+++ b/src/expressions/loop-expr.md
@@ -5,24 +5,21 @@
 > &nbsp;&nbsp; [_LoopLabel_]<sup>?</sup> (\
 > &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; [_InfiniteLoopExpression_]\
 > &nbsp;&nbsp; &nbsp;&nbsp; | [_PredicateLoopExpression_]\
-> &nbsp;&nbsp; &nbsp;&nbsp; | [_PredicatePatternLoopExpression_]\
 > &nbsp;&nbsp; &nbsp;&nbsp; | [_IteratorLoopExpression_]\
 > &nbsp;&nbsp; )
 
 [_LoopLabel_]: #loop-labels
 [_InfiniteLoopExpression_]: #infinite-loops
 [_PredicateLoopExpression_]: #predicate-loops
-[_PredicatePatternLoopExpression_]: #predicate-pattern-loops
 [_IteratorLoopExpression_]: #iterator-loops
 
-Rust supports four loop expressions:
+Rust supports three 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.
 
-All four types of loop support [`break` expressions](#break-expressions), [`continue` expressions](#continue-expressions), and [labels](#loop-labels).
+All three types of loop support [`break` expressions](#break-expressions), [`continue` expressions](#continue-expressions), and [labels](#loop-labels).
 Only `loop` supports [evaluation to non-trivial values](#break-and-loop-values).
 
 ## Infinite loops
@@ -40,12 +37,28 @@ A `loop` expression containing associated [`break` expression(s)](#break-express
 ## Predicate loops
 
 > **<sup>Syntax</sup>**\
-> _PredicateLoopExpression_ :\
-> &nbsp;&nbsp; `while` [_Expression_]<sub>_except struct expression_</sub> [_BlockExpression_]
-
-A `while` loop begins by evaluating the [boolean] loop conditional operand.
-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.
+> [_PredicateLoopExpression_] :\
+> &nbsp;&nbsp; `while` _WhileConditions_ [_BlockExpression_]
+>
+> _WhileConditions_ :\
+> &nbsp;&nbsp; _WhileCondition_ ( && _WhileCondition_ )*
+>
+> _WhileCondition_ :\
+> &nbsp;&nbsp; &nbsp;&nbsp; [_Expression_]<sub>_except struct expression_</sub>\
+> &nbsp;&nbsp; | `let` [_Pattern_] `=` [_Scrutinee_]
+
+A `while` loop expression allows repeating the evaluation of a block while a set of conditions remain true.
+The syntax of a `while` expression is a sequence of one or more condition operands separated by `&&`,
+followed by a [_BlockExpression_].
+
+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.
+After the loop body successfully executes, the condition operands are re-evaluated to determine if the body should be executed again.
+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.
+
+A `while` expression evaluates to `()`.
 
 An example:
 
@@ -58,17 +71,10 @@ while i < 10 {
 }
 ```
 
-## Predicate pattern loops
-
-> **<sup>Syntax</sup>**\
-> [_PredicatePatternLoopExpression_] :\
-> &nbsp;&nbsp; `while` `let` [_Pattern_] `=` [_Scrutinee_]<sub>_except lazy boolean operator expression_</sub>
->              [_BlockExpression_]
-
+### `while let` patterns
 
-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.
-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];
@@ -115,7 +121,28 @@ while let Some(v @ 1) | Some(v @ 2) = vals.pop() {
 }
 ```
 
-As is the case in [`if let` expressions], the scrutinee cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_].
+As is the case in [`if` expressions], the scrutinee cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_].
+
+### `while` condition chains
+
+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;
+    }
+}
+```
 
 ## Iterator loops
 
@@ -233,7 +260,7 @@ A `break` expression is only permitted in the body of a loop, and has one of the
 > &nbsp;&nbsp; `continue` [LIFETIME_OR_LABEL]<sup>?</sup>
 
 When `continue` is encountered, the current iteration of the associated loop body is immediately terminated, returning control to the loop *head*.
-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.
 In the case of a `for` loop, the head is the call-expression controlling the loop.
 
 Like `break`, `continue` is normally associated with the innermost enclosing loop, but `continue 'label` may be used to specify the loop affected.
@@ -264,11 +291,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 8caeff200..e0643fe2a 100644
--- a/src/expressions/struct-expr.md
+++ b/src/expressions/struct-expr.md
@@ -131,7 +131,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 fd8f50cd0..26bce0bd1 100644
--- a/src/names.md
+++ b/src/names.md
@@ -90,13 +90,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 14811697c..1c94745d8 100644
--- a/src/names/namespaces.md
+++ b/src/names/namespaces.md
@@ -118,14 +118,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 5c81ecd87..3a1c609bf 100644
--- a/src/patterns.md
+++ b/src/patterns.md
@@ -69,7 +69,7 @@ Patterns are used in:
   parameters
 * [`match` expressions](expressions/match-expr.md)
 * [`if let` expressions](expressions/if-expr.md)
-* [`while let` expressions](expressions/loop-expr.md#predicate-pattern-loops)
+* [`while let` expressions](expressions/loop-expr.md#while-let-patterns)
 * [`for` expressions](expressions/loop-expr.md#iterator-loops)
 
 ## Destructuring
diff --git a/src/tokens.md b/src/tokens.md
index 197c20147..71a3527fd 100644
--- a/src/tokens.md
+++ b/src/tokens.md
@@ -710,7 +710,7 @@ Similarly the `r`, `b`, and `br` prefixes used in raw string literals, byte lite
 [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
 [keywords]: keywords.md
 [lazy-bool]: expressions/operator-expr.md#lazy-boolean-operators
 [literal expressions]: expressions/literal-expr.md
@@ -738,4 +738,4 @@ Similarly the `r`, `b`, and `br` prefixes used in raw string literals, byte lite
 [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