Skip to content

Commit

Permalink
Merge pull request #1456 from RalfJung/const-pattern
Browse files Browse the repository at this point in the history
update patterns.md for const pattern RFC
  • Loading branch information
ehuss authored May 27, 2024
2 parents 1bf2cdc + 2f63507 commit 0e07fc5
Showing 1 changed file with 23 additions and 12 deletions.
35 changes: 23 additions & 12 deletions src/patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,6 @@ Since negative numbers are not [literals], literal patterns also accept an optio

<div class="warning">

Floating-point literals are currently accepted, but due to the complexity of comparing them, they are going to be forbidden on literal patterns in a future version of Rust (see [issue #41620](https://github.com/rust-lang/rust/issues/41620)).

</div>

<div class="warning">

C string and raw C string literals are accepted in literal patterns, but `&CStr`
doesn't implement structural equality (`#[derive(Eq, PartialEq)]`) and therefore
any such `match` on a `&CStr` will be rejected with a type error.
Expand Down Expand Up @@ -455,6 +449,7 @@ If the bounds is written as a path, after macro resolution, the path must resolv

The type and value of the bounds is dependent upon how it is written out.
If the bounds is a [path], the pattern has the type and value of the [constant] the path resolves to.
For float range patterns, the constant may not be a `NaN`.
If it is a literal, it has the type and value of the corresponding [literal expression].
If is a literal preceded by a `-`, it has the same type as the corresponding [literal expression] and the value of [negating] the value of the corresponding literal expression.

Expand Down Expand Up @@ -538,9 +533,6 @@ For example, `0u8..=255u8` is irrefutable.
The range of values for an integer type is the closed range from its minimum to maximum value.
The range of values for a `char` type are precisely those ranges containing all Unicode Scalar Values: `'\u{0000}'..='\u{D7FF}'` and `'\u{E000}'..='\u{10FFFF}'`.

Floating point range patterns are deprecated and may be removed in a future Rust release.
See [issue #41620](https://github.com/rust-lang/rust/issues/41620) for more information.

> **Edition Differences**: Before the 2021 edition, range patterns with both a lower and upper bound may also be written using `...` in place of `..=`, with the same meaning.
## Reference patterns
Expand Down Expand Up @@ -791,12 +783,31 @@ Unqualified path patterns can refer to:

Qualified path patterns can only refer to associated constants.

Constants cannot be a union type.
Struct and enum constants must have `#[derive(PartialEq, Eq)]` (not merely implemented).

Path patterns are irrefutable when they refer to structs or an enum variant when the enum has only one variant or a constant whose type is irrefutable.
They are refutable when they refer to refutable constants or enum variants for enums with multiple variants.

### Constant patterns

When a constant `C` of type `T` is used as a pattern, we first check that `T: PartialEq`.
Furthermore we require that the value of `C` *has (recursive) structural equality*, which is defined recursively as follows:

- Integers as well as `str`, `bool` and `char` values always have structural equality.
- Tuples, arrays, and slices have structural equality if all their fields/elements have structural equality.
(In particular, `()` and `[]` always have structural equality.)
- References have structural equality if the value they point to has structural equality.
- A value of `struct` or `enum` type has structural equality if its `PartialEq` instance is derived via `#[derive(PartialEq)]`,
and all fields (for enums: of the active variant) have structural equality.
- A raw pointer has structural equality if it was defined as a constant integer (and then cast/transmuted).
- A float value has structural equality if it is not a `NaN`.
- Nothing else has structural equality.

In particular, the value of `C` must be known at pattern-building time (which is pre-monomorphization).
This means that associated consts that involve generic parameters cannot be used as patterns.

After ensuring all conditions are met, the constant value is translated into a pattern, and now behaves exactly as-if that pattern had been written directly.
In particular, it fully participates in exhaustiveness checking.
(For raw pointers, constants are the only way to write such patterns. Only `_` is ever considered exhaustive for these types.)

## Or-patterns

_Or-patterns_ are patterns that match on one of two or more sub-patterns (for example `A | B | C`).
Expand Down

0 comments on commit 0e07fc5

Please sign in to comment.