Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions src/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,109 @@ Language changes in Rust 1.95.0
-------------------------------

- `Stabilize if let guards on match arms <https://github.com/rust-lang/rust/pull/141295>`_

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 <https://github.com/rust-lang/rust/pull/146832>`_

- Lints are outside the scope of the FLS.
Expand Down
5 changes: 5 additions & 0 deletions src/entities-and-resolution.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
221 changes: 200 additions & 21 deletions src/expressions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Comment thread
kirtchev-adacore marked this conversation as resolved.

: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

Expand Down Expand Up @@ -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`.
Expand All @@ -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 <match arm body>` shall be
:t:`unifiable`.
Expand All @@ -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`
Expand Down Expand Up @@ -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.
Comment thread
kirtchev-adacore marked this conversation as resolved.
Outdated

#. :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
Comment thread
kirtchev-adacore marked this conversation as resolved.
Outdated
: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
Comment thread
kirtchev-adacore marked this conversation as resolved.
Outdated
: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

Expand All @@ -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::<i32>()
&& number > 9 => "big number",
Some(_) => "other text",
None => "no text"
}
}

.. _fls_8l74abhlxzdl:

Return Expressions
Expand Down
Loading
Loading