From 3fb728d154b24ee4b8b67d5fabffa3ad1434249a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 26 Jan 2024 17:38:38 +0100 Subject: [PATCH 1/3] update patterns.md for const pattern RFC --- src/patterns.md | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/patterns.md b/src/patterns.md index 6088973d0..e9eb13d14 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -144,12 +144,6 @@ Since negative numbers are not [literals], literal patterns also accept an optio
-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)). - -
- -
- 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. @@ -451,6 +445,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. @@ -534,9 +529,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. > **Note**: Although range patterns use the same syntax as [range expressions], there are no exclusive range patterns. @@ -776,12 +768,30 @@ 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 `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). + +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`). From c6719b5d8dc04f8855f0c1e3ee2bb798465c793b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 3 May 2024 16:08:14 +0200 Subject: [PATCH 2/3] mention associated consts --- src/patterns.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/patterns.md b/src/patterns.md index e9eb13d14..96bd827b7 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -787,6 +787,7 @@ Furthermore we require that the value of `C` *has (recursive) structural equalit - 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 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. From 2f63507ae20c2e2223258a58153ff6af54c965a7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 7 May 2024 08:15:24 +0200 Subject: [PATCH 3/3] clarifications --- src/patterns.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/patterns.md b/src/patterns.md index 96bd827b7..b413c59f1 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -776,7 +776,7 @@ They are refutable when they refer to refutable constants or enum variants for e 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 `bool` and `char` values always have structural equality. +- 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. @@ -787,7 +787,7 @@ Furthermore we require that the value of `C` *has (recursive) structural equalit - 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 cannot be used as patterns. +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.