From 3e10ae3bbb46a9070b4232d3fe64ff5f1a22c438 Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 3 Feb 2022 19:31:43 +0100 Subject: [PATCH 1/3] Document let else statements --- src/statements.md | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/statements.md b/src/statements.md index 8d9c21d7d..67e77efaa 100644 --- a/src/statements.md +++ b/src/statements.md @@ -54,17 +54,27 @@ fn outer() { > **Syntax**\ > _LetStatement_ :\ >    [_OuterAttribute_]\* `let` [_PatternNoTopAlt_] -> ( `:` [_Type_] )? (`=` [_Expression_] )? `;` - -A *`let` statement* introduces a new set of [variables], given by an -irrefutable [pattern]. The pattern is followed optionally by a type -annotation and then optionally by an initializer expression. When no -type annotation is given, the compiler will infer the type, or signal +> ( `:` [_Type_] )? (`=` [_Expression_] [†](#let-else-restriction) +> ( `else` [_BlockExpression_]) ? ) ? `;` +> +> † When an `else` block is specified, the +> _Expression_ must not be a [_LazyBooleanExpression_], or end with a `}`. + +A *`let` statement* introduces a new set of [variables], given by a [pattern]. +The pattern is followed optionally by a type annotation and then either ends, +or is followed by an initializer expression plus an optional `else` block. +When no type annotation is given, the compiler will infer the type, or signal an error if insufficient type information is available for definite inference. Any variables introduced by a variable declaration are visible from the point of declaration until the end of the enclosing block scope, except when they are shadowed by another variable declaration. +If an `else` block is not present, the pattern must be irrefutable. +If an `else` block is present, the pattern may be refutable. +If the pattern does not match (this requires it to be refutable), the `else` +block is executed. +The `else` block must always diverge (evaluate to the [never type]). + ## Expression statements > **Syntax**\ @@ -121,6 +131,7 @@ statement are [`cfg`], and [the lint check attributes]. [function]: items/functions.md [item]: items.md [module]: items/modules.md +[never type]: types/never.md [canonical path]: paths.md#canonical-paths [implementations]: items/implementations.md [variables]: variables.md @@ -128,9 +139,11 @@ statement are [`cfg`], and [the lint check attributes]. [`cfg`]: conditional-compilation.md [the lint check attributes]: attributes/diagnostics.md#lint-check-attributes [pattern]: patterns.md +[_BlockExpression_]: expressions/block-expr.md [_ExpressionStatement_]: #expression-statements [_Expression_]: expressions.md [_Item_]: items.md +[_LazyBooleanExpression_]: expressions/operator-expr.md#lazy-boolean-operators [_LetStatement_]: #let-statements [_MacroInvocationSemi_]: macros.md#macro-invocation [_OuterAttribute_]: attributes.md From a50e43ee796f0cc8266701736af0a287f6bc54c7 Mon Sep 17 00:00:00 2001 From: est31 Date: Tue, 20 Sep 2022 04:28:31 +0200 Subject: [PATCH 2/3] Add example --- src/statements.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/statements.md b/src/statements.md index 67e77efaa..7acb0dc25 100644 --- a/src/statements.md +++ b/src/statements.md @@ -75,6 +75,17 @@ If the pattern does not match (this requires it to be refutable), the `else` block is executed. The `else` block must always diverge (evaluate to the [never type]). +```rust +let (mut v, w) = (vec![1, 2, 3], 42); // The bindings may be mut or const +let Some(t) = v.pop() else { // Refutable patterns require an else block + panic!(); // The else block must diverge +}; +let [u, v] = [v[0], v[1]] else { // This pattern is irrefutable, so the compiler + // will lint as the else block is redundant. + panic!(); +}; +``` + ## Expression statements > **Syntax**\ From 9e6a8c029e142810b0f1dd7421c8aacab399aec6 Mon Sep 17 00:00:00 2001 From: est31 Date: Mon, 26 Sep 2022 09:26:12 +0200 Subject: [PATCH 3/3] let bindings can now be refutable too --- src/items/functions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/items/functions.md b/src/items/functions.md index 325588a53..5b4ac7af6 100644 --- a/src/items/functions.md +++ b/src/items/functions.md @@ -59,8 +59,8 @@ fn answer_to_life_the_universe_and_everything() -> i32 { ## Function parameters -As with `let` bindings, function parameters are irrefutable [patterns], so any -pattern that is valid in a let binding is also valid as a parameter: +Function parameters are irrefutable [patterns], so any pattern that is valid in +an else-less `let` binding is also valid as a parameter: ```rust fn first((value, _): (i32, i32)) -> i32 { value }