From f3c4c362b85c75e2d6b2d7e9f55869d14ae864e6 Mon Sep 17 00:00:00 2001 From: Pete LeVasseur Date: Tue, 7 Jul 2026 02:48:52 +0900 Subject: [PATCH 1/2] docs(match-guards): document if-let guards --- src/changelog.rst | 103 +++++++++++++ src/entities-and-resolution.rst | 5 + src/expressions.rst | 221 ++++++++++++++++++++++++--- src/glossary.rst | 56 ++++++- src/ownership-and-deconstruction.rst | 40 ++++- src/patterns.rst | 14 +- src/types-and-traits.rst | 9 +- 7 files changed, 414 insertions(+), 34 deletions(-) diff --git a/src/changelog.rst b/src/changelog.rst index 8ea20f53..bdd47665 100644 --- a/src/changelog.rst +++ b/src/changelog.rst @@ -23,6 +23,109 @@ Language changes in Rust 1.95.0 ------------------------------- - `Stabilize if let guards on match arms `_ + + Changed syntax: :s:`MatchArmGuard` + + The FLS models the Rust 2021 syntax accepted by stable :t:`rustc` 1.95.0. + It does not add the Rust Reference's attribute position before a guard + ``let`` pattern because attributes remain unstable in that position. + + New syntax: + + - :s:`MatchArmGuardChain` + - :s:`MatchArmGuardCondition` + - :s:`MatchArmGuardConditionOperand` + - :s:`MatchArmGuardConditions` + - :s:`MatchArmGuardLetPattern` + - :s:`MatchArmGuardOperand` + - :s:`MatchArmGuardScrutinee` + + New glossary entries: + + - :t:`match arm guard chain` + - :t:`match arm guard condition` + - :t:`match arm guard condition operand` + - :t:`match arm guard let pattern` + - :t:`match arm guard operand` + - :t:`match arm guard scrutinee` + + Updated glossary entries: + + - :t:`let binding` + + Changed existing paragraphs: + + - :p:`fls_72JHo343O7jp` + - :p:`fls_6bwTtGKb7ba7` + - :p:`fls_bzhz5wjd90ii` + - :p:`fls_st9onPgDrc8y` + - :p:`fls_4dv7x9nh2h4e` + - :p:`fls_sbtx1l6n2tp2` + - :p:`fls_e02um1gb89d0` + - :p:`fls_lbsfhg42yiqy` + - :p:`fls_fnvr5w2wzxns` + - :p:`fls_ptk6yibqyfzi` + - :p:`fls_a5tmilqxdb6f` + + New paragraphs: + + - :p:`fls_3TGpt9OGydQi` + - :p:`fls_7OkU5RVrAyev` + - :p:`fls_Uv7QsP2nKcDx` + - :p:`fls_DT4N2rr6wpvZ` + - :p:`fls_gNQBzI92IAir` + - :p:`fls_Er5TmL9bXwVq` + - :p:`fls_AAuyKfxLgJ43` + - :p:`fls_Yq4NhC8sRpJm` + - :p:`fls_kM6dZv3PaNqT` + - :p:`fls_Lc8EwS5rYpBn` + - :p:`fls_Nc6JvS9rFaLm` + - :p:`fls_Qr3TcH8vNpKs` + - :p:`fls_Lm5WqZ2dJvYp` + - :p:`fls_Bx8KsV4nQdRt` + - :p:`fls_Mv2YpG7sLcHw` + - :p:`fls_Xd4LqN9vTrPm` + - :p:`fls_Hw6CkR3mVzQn` + - :p:`fls_gfD9XwVj5hab` + - :p:`fls_Zm9VxF5pQwLd` + - :p:`fls_Dp8aJr2LqYwS` + - :p:`fls_Wm4QvN7xTcRb` + - :p:`fls_Ks9FdL3pVxQa` + - :p:`fls_Rt5XcG8nMbPw` + - :p:`fls_Yh2NqT6vLsCk` + - :p:`fls_Cw2RsH7pVnQx` + - :p:`fls_Pb7MzD4wQkXe` + - :p:`fls_Fj8QpM3dLsVt` + - :p:`fls_Qf4VnH8sMxRa` + - :p:`fls_Kz7NvR2xYpWm` + - :p:`fls_Zc6TbK2wLpNd` + - :p:`fls_Bd9TmL4qVcNs` + - :p:`fls_Rp5HxK8wJqYd` + - :p:`fls_Vr9MqJ5xNsYd` + - :p:`fls_Nt6QmC3sLpXz` + - :p:`fls_Av4JyT9nMkRp` + - :p:`fls_Gc5RpT8nYvQm` + - :p:`fls_Nw2KxL7qVmRs` + - :p:`fls_Rh9TsD4vQpLm` + - :p:`fls_8Vrz9SNfjSh7` + - :p:`fls_X4y3QltM208J` + - :p:`fls_vQ3tHg9XmDkF` + - :p:`fls_Td7McP9rQxVn` + - :p:`fls_Jp4NsK8vYqRc` + - :p:`fls_Vq8LdN2xWmTs` + - :p:`fls_Et6PqW9nRcVm` + - :p:`fls_7yybrl2J37Et` + + Removed paragraphs: + + - :p:`fls_k7kliy101m0f` + - :p:`fls_k68zkb6jv0vz` + - :p:`fls_gbb6wbmher5z` + - :p:`fls_jl4av757yx8j` + - :p:`fls_wkh5wztauwhu` + - :p:`fls_f5f0x8jstp1g` + - :p:`fls_yk8l9zjh7i0d` + - `irrefutable_let_patterns lint no longer lints on let chains `_ - Lints are outside the scope of the FLS. diff --git a/src/entities-and-resolution.rst b/src/entities-and-resolution.rst index 1a9222ee..30e1fae8 100644 --- a/src/entities-and-resolution.rst +++ b/src/entities-and-resolution.rst @@ -496,6 +496,11 @@ related :t:`let statement` appears. The :t:`binding` of a :t:`match arm` is :t:`in scope` within its related :t:`[expression]s` and related :t:`match arm guard`. +:dp:`fls_Td7McP9rQxVn` +Each :t:`let binding` introduced by a :t:`match arm guard let pattern` is +:t:`in scope` within the following :t:`[match arm guard condition]s` of the +same :t:`match arm guard` and within the related :t:`match arm body`. + :dp:`fls_eBacCVlDaKYK` A :t:`binding` declared outside of a :t:`const block expression` is not :t:`in scope` within such a :t:`const block expression`. diff --git a/src/expressions.rst b/src/expressions.rst index e9696884..81fc4fea 100644 --- a/src/expressions.rst +++ b/src/expressions.rst @@ -4645,7 +4645,38 @@ Match Expressions OuterAttributeOrDoc* Pattern MatchArmGuard? MatchArmGuard ::= - $$if$$ Operand + $$if$$ MatchArmGuardConditions + + MatchArmGuardConditions ::= + MatchArmGuardChain + | MatchArmGuardOperand + + MatchArmGuardOperand ::= + Operand + + MatchArmGuardChain ::= + MatchArmGuardCondition ($$&&$$ MatchArmGuardCondition)* + + MatchArmGuardCondition ::= + MatchArmGuardConditionOperand + | MatchArmGuardLetPattern + + MatchArmGuardLetPattern ::= + $$let$$ Pattern $$=$$ MatchArmGuardScrutinee + +:dp:`fls_3TGpt9OGydQi` +A :ds:`MatchArmGuardConditionOperand` is any expression in category +:s:`Expression`, except expressions in categories :s:`AssignmentExpression`, +:s:`CompoundAssignmentExpression`, :s:`LazyBooleanExpression`, +:s:`RangeFromExpression`, :s:`RangeFromToExpression`, and +:s:`RangeInclusiveExpression`. + +:dp:`fls_7OkU5RVrAyev` +A :ds:`MatchArmGuardScrutinee` is any expression in category +:s:`Expression`, except expressions in categories :s:`AssignmentExpression`, +:s:`CompoundAssignmentExpression`, :s:`LazyBooleanExpression`, +:s:`RangeFromExpression`, :s:`RangeFromToExpression`, and +:s:`RangeInclusiveExpression`. .. rubric:: Legality Rules @@ -4679,6 +4710,31 @@ A :t:`match arm body` is the :t:`operand` of a :t:`match arm`. A :t:`match arm guard` is a :t:`construct` that provides additional filtering to a :t:`match arm matcher`. +:dp:`fls_Uv7QsP2nKcDx` +A :t:`match arm guard operand` is the :t:`operand` of a :t:`match arm guard` +that does not have a :t:`match arm guard chain`. + +:dp:`fls_DT4N2rr6wpvZ` +A :t:`match arm guard chain` is a sequence of one or more +:t:`[match arm guard condition]s`, separated by ``&&``. + +:dp:`fls_gNQBzI92IAir` +A :t:`match arm guard` that contains a :t:`match arm guard let pattern` has a +:t:`match arm guard chain`; otherwise it has a :t:`match arm guard operand`. + +:dp:`fls_Er5TmL9bXwVq` +A :t:`match arm guard condition operand` is a :t:`match arm guard condition` +that consists of an :t:`expression`. + +:dp:`fls_AAuyKfxLgJ43` +A :t:`match arm guard let pattern` is a :t:`match arm guard condition` that +consists of a :t:`pattern` and a :t:`match arm guard scrutinee`. + +:dp:`fls_Yq4NhC8sRpJm` +A :t:`match arm guard scrutinee` is the :t:`expression` of a +:t:`match arm guard let pattern` whose :t:`value` is matched against the +:t:`pattern` of that :t:`match arm guard let pattern`. + :dp:`fls_RPMOAaZ6lflI` :t:`[Binding]s` introduced in the :t:`pattern` of a :t:`match arm matcher` are :t:`immutable` in the :t:`match arm guard`. @@ -4688,9 +4744,17 @@ The :t:`type` of the :t:`subject expression` and the :t:`[type]s` of all :t:`[pattern]s` of all :t:`[match arm matcher]s` shall be :t:`unifiable`. :dp:`fls_bzhz5wjd90ii` -The :t:`type` of the :t:`operand` of a :t:`match arm guard` shall be :t:`type` +The :t:`type` of a :t:`match arm guard operand` shall be :t:`type` :c:`bool`. + +:dp:`fls_kM6dZv3PaNqT` +The :t:`type` of a :t:`match arm guard condition operand` shall be :t:`type` :c:`bool`. +:dp:`fls_Lc8EwS5rYpBn` +The :t:`expected type` of the :t:`pattern` of a +:t:`match arm guard let pattern` is the :t:`type` of its +:t:`match arm guard scrutinee`. + :dp:`fls_17ag0wzdbxv6` The :t:`[type]s` of all :t:`match arm bodies ` shall be :t:`unifiable`. @@ -4708,8 +4772,9 @@ A :t:`match arm` is selected when its :t:`pattern` matches the :t:`Match arm` selection happens in declarative order. :dp:`fls_e02um1gb89d0` -The :t:`[pattern]s` of all :t:`[match arm]s` taken together shall exhaustively -match the :t:`[subject expression]'s` :t:`type`. +The :t:`[pattern]s` of all :t:`[match arm]s` without a +:t:`match arm guard` taken together shall exhaustively match the +:t:`[subject expression]'s` :t:`type`. :dp:`fls_4sh2yrslszvb` The :t:`value` of a :t:`match expression` is the :t:`value` of the :t:`operand` @@ -4742,35 +4807,133 @@ The :t:`evaluation` of a :t:`match expression` proceeds as follows: Otherwise control proceeds with the :t:`evaluation` of the next :t:`match arm`. +:dp:`fls_Nc6JvS9rFaLm` +When the :t:`pattern` of a :t:`match arm matcher` is an :t:`or-pattern`, each +:t:`pattern-without-alternation` of the :t:`or-pattern` is considered in source +order during :t:`evaluation` of the :t:`match arm matcher`. Otherwise, the +:t:`pattern` itself is considered. + :dp:`fls_4dv7x9nh2h4e` The :t:`evaluation` of a :t:`match arm matcher` proceeds as follows: -#. :dp:`fls_k7kliy101m0f` - The :t:`pattern` of the :t:`match arm matcher` is evaluated. +#. :dp:`fls_Qr3TcH8vNpKs` + Each :t:`pattern` determined by :p:`fls_Nc6JvS9rFaLm` is considered in + source order as follows: + + #. :dp:`fls_Lm5WqZ2dJvYp` + If :t:`pattern matching` with the :t:`pattern` and the :t:`value` of the + :t:`subject expression` fails, then evaluation continues with the next + :t:`pattern`, if any. -#. :dp:`fls_k68zkb6jv0vz` - If the :t:`pattern` succeeds, then + #. :dp:`fls_Bx8KsV4nQdRt` + If :t:`pattern matching` with the :t:`pattern` succeeds, then: - #. :dp:`fls_gbb6wbmher5z` - If the :t:`match arm matcher` has a :t:`match arm guard`, then + #. :dp:`fls_Mv2YpG7sLcHw` + If the :t:`match arm matcher` has no :t:`match arm guard`, then the + :t:`match arm matcher` succeeds and its :t:`evaluation` is complete. - #. :dp:`fls_jl4av757yx8j` - The :t:`match arm guard` is evaluated. + #. :dp:`fls_Xd4LqN9vTrPm` + If the :t:`match arm matcher` has a :t:`match arm guard`, then the + :t:`match arm guard` is evaluated. - #. :dp:`fls_wkh5wztauwhu` + #. :dp:`fls_Hw6CkR3mVzQn` If the :t:`match arm guard` evaluates to ``true``, then the - :t:`match arm matcher` succeeds. + :t:`match arm matcher` succeeds and its :t:`evaluation` is complete. - #. :dp:`fls_f5f0x8jstp1g` - Otherwise the :t:`match arm matcher` fails. + #. :dp:`fls_gfD9XwVj5hab` + If the :t:`match arm guard` evaluates to ``false``, then the + :t:`drop scope` of the related :t:`match arm` is left, and evaluation + continues with the next :t:`pattern`, including later + :t:`[pattern-without-alternation]s` of the same :t:`or-pattern`. -#. :dp:`fls_yk8l9zjh7i0d` - Otherwise the :t:`match arm matcher` fails. +#. :dp:`fls_Zm9VxF5pQwLd` + If no considered :t:`pattern` causes the :t:`match arm matcher` to succeed, + then the :t:`match arm matcher` fails. :dp:`fls_sbtx1l6n2tp2` -The :t:`evaluation` of a :t:`match arm guard` evaluates its :t:`operand`. A -:t:`match arm guard` evaluates to ``true`` when its :t:`operand` evaluates to -``true``, otherwise it evaluates to ``false``. +The :t:`evaluation` of a :t:`match arm guard` proceeds as follows: + +#. :dp:`fls_Dp8aJr2LqYwS` + If the :t:`match arm guard` has a :t:`match arm guard operand`, then: + + #. :dp:`fls_Wm4QvN7xTcRb` + The :t:`match arm guard operand` is evaluated. + + #. :dp:`fls_Ks9FdL3pVxQa` + If the :t:`match arm guard operand` evaluates to ``false``, then the + :t:`match arm guard` evaluates to ``false`` and its :t:`evaluation` is + complete. + + #. :dp:`fls_Rt5XcG8nMbPw` + If the :t:`match arm guard operand` evaluates to ``true``, then the + :t:`match arm guard` evaluates to ``true`` and its :t:`evaluation` is + complete. + +#. :dp:`fls_Yh2NqT6vLsCk` + Otherwise, the :t:`match arm guard` has a :t:`match arm guard chain`, and: + + #. :dp:`fls_Cw2RsH7pVnQx` + Each :t:`match arm guard condition` of the chain is evaluated in source + order as follows: + + #. :dp:`fls_Pb7MzD4wQkXe` + If the :t:`match arm guard condition` is a + :t:`match arm guard condition operand`, then: + + #. :dp:`fls_Fj8QpM3dLsVt` + The :t:`match arm guard condition operand` is evaluated. + + #. :dp:`fls_Qf4VnH8sMxRa` + If the :t:`match arm guard condition operand` evaluates to + ``false``, then the :t:`match arm guard` evaluates to ``false`` and + no later :t:`[match arm guard condition]s` are evaluated. + + #. :dp:`fls_Kz7NvR2xYpWm` + If the :t:`match arm guard condition operand` evaluates to + ``true``, then evaluation continues with the next + :t:`match arm guard condition`, if any. + + #. :dp:`fls_Zc6TbK2wLpNd` + If the :t:`match arm guard condition` is a + :t:`match arm guard let pattern`, then: + + #. :dp:`fls_Bd9TmL4qVcNs` + The :t:`match arm guard scrutinee` is evaluated. + + #. :dp:`fls_Rp5HxK8wJqYd` + :t:`Pattern matching` is performed with the :t:`pattern` of the + :t:`match arm guard let pattern` against the resulting :t:`value`. + + #. :dp:`fls_Vr9MqJ5xNsYd` + If the :t:`pattern matching` fails, then the + :t:`match arm guard` evaluates to ``false`` and no later + :t:`[match arm guard condition]s` are evaluated. + + #. :dp:`fls_Nt6QmC3sLpXz` + If the :t:`pattern matching` succeeds, then any :t:`[binding]s` + introduced by the :t:`pattern` are bound to the matched + :t:`[value]s` as described in :p:`fls_t34oqarwcusu`, and evaluation + continues with the next :t:`match arm guard condition`, if any. + + #. :dp:`fls_Av4JyT9nMkRp` + If every :t:`match arm guard condition` of the chain has been evaluated + without the :t:`match arm guard` evaluating to ``false``, then the + :t:`match arm guard` evaluates to ``true``. + +:dp:`fls_Gc5RpT8nYvQm` +During the :t:`evaluation` of a :t:`match arm guard`, each :t:`binding` +introduced by the :t:`pattern` of the related :t:`match arm matcher` is +accessed through a shared reference to the matched part of the +:t:`subject expression`'s :t:`value`. + +:dp:`fls_Nw2KxL7qVmRs` +If the :t:`binding mode` of such a :t:`binding` is :t:`by value`, then the copy +or move described by :p:`fls_pxvtqxke1enp` is performed only if the related +:t:`match arm guard` evaluates to ``true``. + +:dp:`fls_Rh9TsD4vQpLm` +If the related :t:`match arm guard` evaluates to ``false``, then no copy or +move into such a :t:`binding` is performed. .. rubric:: Examples @@ -4785,6 +4948,22 @@ The :t:`evaluation` of a :t:`match arm guard` evaluates its :t:`operand`. A } } +:dp:`fls_8Vrz9SNfjSh7` +A match arm guard chain consisting of a match arm guard let pattern followed by +a match arm guard condition operand. + +.. code-block:: rust + + fn categorize(input: Option<&str>) -> &'static str { + match input { + Some(text) + if let Ok(number) = text.parse::() + && number > 9 => "big number", + Some(_) => "other text", + None => "no text" + } + } + .. _fls_8l74abhlxzdl: Return Expressions diff --git a/src/glossary.rst b/src/glossary.rst index d7d53531..c6fc3abe 100644 --- a/src/glossary.rst +++ b/src/glossary.rst @@ -2489,7 +2489,9 @@ See :s:`LessThanOrEqualsExpression`. let binding ^^^^^^^^^^^ -A :dt:`let binding` is the :t:`binding` introduced by a :t:`let statement`, an :t:`if let expression`, or a :t:`while let loop expression`. +A :dt:`let binding` is a :t:`binding` introduced by the :t:`pattern` of a +:t:`let statement`, an :t:`if let expression`, a :t:`while let loop expression`, +or a :t:`match arm guard let pattern`. let initializer ^^^^^^^^^^^^^^^ @@ -2766,6 +2768,58 @@ to a :t:`match arm matcher`. See :s:`MatchArmGuard`. +match arm guard chain +^^^^^^^^^^^^^^^^^^^^^ + +A :dt:`match arm guard chain` is a sequence of one or more +:t:`[match arm guard condition]s`, separated by ``&&``. + +See :s:`MatchArmGuardChain`. + +match arm guard condition +^^^^^^^^^^^^^^^^^^^^^^^^^ + +A :dt:`match arm guard condition` is a component of a +:t:`match arm guard chain` that is either a +:t:`match arm guard condition operand` or a +:t:`match arm guard let pattern`. + +See :s:`MatchArmGuardCondition`. + +match arm guard condition operand +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A :dt:`match arm guard condition operand` is a :t:`match arm guard condition` +that consists of an :t:`expression`. + +See :s:`MatchArmGuardConditionOperand`. + +match arm guard let pattern +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A :dt:`match arm guard let pattern` is a :t:`match arm guard condition` that +consists of a :t:`pattern` and a :t:`match arm guard scrutinee`, and introduces +the :t:`[binding]s` of its :t:`pattern` when :t:`pattern matching` succeeds. + +See :s:`MatchArmGuardLetPattern`. + +match arm guard operand +^^^^^^^^^^^^^^^^^^^^^^^ + +A :dt:`match arm guard operand` is the :t:`operand` of a :t:`match arm guard` +that does not have a :t:`match arm guard chain`. + +See :s:`MatchArmGuardOperand`. + +match arm guard scrutinee +^^^^^^^^^^^^^^^^^^^^^^^^^ + +A :dt:`match arm guard scrutinee` is the :t:`expression` of a +:t:`match arm guard let pattern` whose :t:`value` is matched against the +:t:`pattern` of that :t:`match arm guard let pattern`. + +See :s:`MatchArmGuardScrutinee`. + match arm matcher ^^^^^^^^^^^^^^^^^ diff --git a/src/ownership-and-deconstruction.rst b/src/ownership-and-deconstruction.rst index c77ca103..a8c035ec 100644 --- a/src/ownership-and-deconstruction.rst +++ b/src/ownership-and-deconstruction.rst @@ -502,9 +502,14 @@ following :t:`[construct]s` are :t:`[drop construct]s`: :t:`block expression` that contains the :t:`statement`. * :dp:`fls_lbsfhg42yiqy` - The parent :t:`drop scope` of the :t:`operand` of a :t:`match arm guard` is - the :t:`drop scope` of the :t:`match arm` that contains the - :t:`match arm guard`. + The parent :t:`drop scope` of a :t:`match arm guard operand` or a + :t:`match arm guard condition operand` is the :t:`drop scope` of the + :t:`match arm` that contains the :t:`match arm guard`. + +* :dp:`fls_Jp4NsK8vYqRc` + The parent :t:`drop scope` of the :t:`match arm guard scrutinee` of a + :t:`match arm guard let pattern` is the :t:`drop scope` of the + :t:`match arm` that contains the :t:`match arm guard`. * :dp:`fls_5m3u3k6f00bd` The parent :t:`drop scope` of the :t:`operand` of a :t:`match arm` is the @@ -533,8 +538,9 @@ A :t:`binding` declared in a :t:`let statement` is associated with the :t:`let statement`. :dp:`fls_fnvr5w2wzxns` -A :t:`binding` declared in a :t:`match expression` is associated with the -:t:`drop scope` of the :t:`match arm` of the :t:`match expression`. +A :t:`binding` introduced by the :t:`pattern` of a :t:`match arm matcher`, or a +:t:`let binding` introduced by a :t:`match arm guard let pattern`, is associated +with the :t:`drop scope` of the related :t:`match arm`. :dp:`fls_1vZFa5mDEbXW` A :t:`binding` declared in a :t:`while let loop expression` is associated with @@ -575,7 +581,13 @@ possible :t:`[drop scope]s` are as follows: The :t:`drop scope` of the :t:`operand` of a :t:`match arm`. * :dp:`fls_ptk6yibqyfzi` - The :t:`drop scope` of the :t:`operand` of a :t:`match arm guard`. + The :t:`drop scope` of a :t:`match arm guard operand` or a + :t:`match arm guard condition operand`. + +* :dp:`fls_Vq8LdN2xWmTs` + The :t:`drop scope` of the :t:`match arm` that contains the + :t:`match arm guard`, when the :t:`temporary` is created while evaluating a + :t:`match arm guard scrutinee` of a :t:`match arm guard let pattern`. * :dp:`fls_dltmd8e8c5ia` The :t:`drop scope` of the :t:`right operand` of a @@ -699,8 +711,22 @@ When a :t:`drop scope` is left, all :t:`[value]s` associated with that declaration order, where the declaration order is defined by the first :t:`pattern-without-alternation`. +* :dp:`fls_Et6PqW9nRcVm` + Evaluated :t:`[match arm guard let pattern]s` that have + :t:`[let binding]s` or :t:`[temporary]s` associated with the + :t:`drop scope` of a :t:`match arm` are processed in reverse source order. + For each such pattern, its :t:`[let binding]s`, if any, are dropped in reverse + declaration order before the :t:`[temporary]s` created while evaluating its + :t:`match arm guard scrutinee` are dropped in reverse creation order. + +* :dp:`fls_7yybrl2J37Et` + When a :t:`match arm guard` evaluates to ``false``, the + :t:`[let binding]s` and :t:`[temporary]s` associated with the related + :t:`match arm` are :t:`dropped` before the next :t:`pattern` or + :t:`match arm` is considered. + * :dp:`fls_a5tmilqxdb6f` - :t:`Temporaries ` are :t:`dropped` in reverse creation order. + All other :t:`[temporary]s` are :t:`dropped` in reverse creation order. * :dp:`fls_g07zq3n55094` All other :t:`[binding]s` are :t:`dropped` in reverse declaration order. diff --git a/src/patterns.rst b/src/patterns.rst index 6d2de0b6..b78f2cd9 100644 --- a/src/patterns.rst +++ b/src/patterns.rst @@ -69,11 +69,13 @@ of a :t:`pattern-without-range`, except for when the :t:`pattern` is ``&mut`` with :t:`keyword` ``mut`` containing an :t:`identifier pattern`. :dp:`fls_72JHo343O7jp` -An or-pattern shall not appear in the :t:`pattern-without-alternation` of a -:t:`closure parameter`, a :t:`function parameter`, or a :t:`let binding`. +An :t:`or-pattern` shall not be used as the top-level :t:`pattern` of a +:t:`closure parameter`, a :t:`function parameter`, or a :t:`let statement`. :dp:`fls_6bwTtGKb7ba7` -A :dt:`let binding` is the :t:`binding` introduced by a :t:`let statement`, an :t:`if let expression`, or a :t:`while let loop expression`. +A :dt:`let binding` is a :t:`binding` introduced by the :t:`pattern` of a +:t:`let statement`, an :t:`if let expression`, a :t:`while let loop expression`, +or a :t:`match arm guard let pattern`. :dp:`fls_8luyomzppck` Any two :t:`[subpattern]s` of an :t:`or-pattern` are subject to the following @@ -1297,6 +1299,12 @@ follows: :std:`core::marker::Copy` :t:`trait`, otherwise the :t:`binding` is bound to the move of the matched :t:`value`. +:dp:`fls_X4y3QltM208J` +For a :t:`binding` introduced by the :t:`pattern` of a +:t:`match arm matcher` with a related :t:`match arm guard`, the timing of a +copy or move into a :t:`by value` binding is specified by the +:t:`match arm guard` dynamic semantics. + .. _fls_jm6l7b90h6wa: Pattern Matching diff --git a/src/types-and-traits.rst b/src/types-and-traits.rst index 73768350..f142329d 100644 --- a/src/types-and-traits.rst +++ b/src/types-and-traits.rst @@ -2498,8 +2498,13 @@ The :t:`type inference` rules for :t:`[expression]s` are as follows: the :t:`type` of the :t:`[pattern]s`. #. :dp:`fls_st9onPgDrc8y` - Infer the :t:`[operand]s` of all :t:`[match arm guard]s` with - :t:`expected type` :c:`bool`. + Infer each :t:`match arm guard operand` and each + :t:`match arm guard condition operand` with :t:`expected type` :c:`bool`. + + #. :dp:`fls_vQ3tHg9XmDkF` + Infer each :t:`match arm guard scrutinee` with the :t:`expected type` set + to the :t:`type` of the :t:`pattern` of the related + :t:`match arm guard let pattern`. #. :dp:`fls_F999gqcBfff9` Infer the :t:`match arm body` of every :t:`match arm` with the From f25e095faedb4c502f2934e07e3ac9bd3c6cff27 Mon Sep 17 00:00:00 2001 From: Pete LeVasseur Date: Wed, 8 Jul 2026 06:22:37 +0900 Subject: [PATCH 2/2] docs(match-guards): address review feedback --- src/expressions.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/expressions.rst b/src/expressions.rst index 81fc4fea..77848884 100644 --- a/src/expressions.rst +++ b/src/expressions.rst @@ -4651,9 +4651,6 @@ Match Expressions MatchArmGuardChain | MatchArmGuardOperand - MatchArmGuardOperand ::= - Operand - MatchArmGuardChain ::= MatchArmGuardCondition ($$&&$$ MatchArmGuardCondition)* @@ -4664,6 +4661,9 @@ Match Expressions MatchArmGuardLetPattern ::= $$let$$ Pattern $$=$$ MatchArmGuardScrutinee + MatchArmGuardOperand ::= + Operand + :dp:`fls_3TGpt9OGydQi` A :ds:`MatchArmGuardConditionOperand` is any expression in category :s:`Expression`, except expressions in categories :s:`AssignmentExpression`, @@ -4843,7 +4843,7 @@ The :t:`evaluation` of a :t:`match arm matcher` proceeds as follows: #. :dp:`fls_gfD9XwVj5hab` If the :t:`match arm guard` evaluates to ``false``, then the :t:`drop scope` of the related :t:`match arm` is left, and evaluation - continues with the next :t:`pattern`, including later + continues with the next :t:`pattern`, including subsequent :t:`[pattern-without-alternation]s` of the same :t:`or-pattern`. #. :dp:`fls_Zm9VxF5pQwLd` @@ -4886,7 +4886,7 @@ The :t:`evaluation` of a :t:`match arm guard` proceeds as follows: #. :dp:`fls_Qf4VnH8sMxRa` If the :t:`match arm guard condition operand` evaluates to ``false``, then the :t:`match arm guard` evaluates to ``false`` and - no later :t:`[match arm guard condition]s` are evaluated. + no subsequent :t:`[match arm guard condition]s` are evaluated. #. :dp:`fls_Kz7NvR2xYpWm` If the :t:`match arm guard condition operand` evaluates to @@ -4906,7 +4906,7 @@ The :t:`evaluation` of a :t:`match arm guard` proceeds as follows: #. :dp:`fls_Vr9MqJ5xNsYd` If the :t:`pattern matching` fails, then the - :t:`match arm guard` evaluates to ``false`` and no later + :t:`match arm guard` evaluates to ``false`` and no subsequent :t:`[match arm guard condition]s` are evaluated. #. :dp:`fls_Nt6QmC3sLpXz` @@ -4923,7 +4923,7 @@ The :t:`evaluation` of a :t:`match arm guard` proceeds as follows: :dp:`fls_Gc5RpT8nYvQm` During the :t:`evaluation` of a :t:`match arm guard`, each :t:`binding` introduced by the :t:`pattern` of the related :t:`match arm matcher` is -accessed through a shared reference to the matched part of the +accessed through a :t:`shared reference` to the matched part of the :t:`subject expression`'s :t:`value`. :dp:`fls_Nw2KxL7qVmRs`