Skip to content

Commit a87587e

Browse files
committed
Rewrite Range Patterns with Half Open ranges
This rewrite not only adds half-open ranges to the documentation for stabilizing the feature, it also rewrites the entire section to answer more questions about how they work, like what types the range patterns actually match against.
1 parent 7b1240b commit a87587e

File tree

1 file changed

+49
-12
lines changed

1 file changed

+49
-12
lines changed

src/patterns.md

+49-12
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ match tuple {
389389
>
390390
> _HalfOpenRangePattern_ :\
391391
>    | _RangePatternBound_ `..`
392+
>    | `..=` _RangePatternBound_
392393
>
393394
> _ObsoleteRangePattern_ :\
394395
>    _RangePatternBound_ `...` _RangePatternBound_
@@ -400,26 +401,51 @@ match tuple {
400401
> &nbsp;&nbsp; | `-`<sup>?</sup> [FLOAT_LITERAL]\
401402
> &nbsp;&nbsp; | [_PathExpression_]
402403
403-
Range patterns match values within the range defined by their bounds.
404+
*Range patterns* match scalar values within the range defined by their bounds.
405+
A bound on the left of its sigils is a *lower bound*.
406+
A bound on the right is an *upper bound*.
404407
A range pattern may be closed or half-open.
405-
A range pattern is closed if it has both a lower and an upper bound, and it matches all the values between and including both of its bounds.
406-
A range pattern that is half-open is written with a lower bound but not an upper bound, and matches any value equal to or greater than the specified lower bound.
408+
409+
A range pattern is *closed* if it has both a lower and an upper bound.
410+
The only closed ranged pattern is the inclusive range pattern.
411+
412+
*Inclusive range patterns* match all the values between and including both of its bounds.
413+
It is written as its lower bounds, followed by `..=`, followed by its upper bounds.
414+
The type of it is the type unification of its upper and lower bounds.
407415

408416
For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, `'o'`, and `'p'`.
417+
418+
The lower bound cannot be greater than the upper bound.
419+
That is, in `a..=b`, a &le; b must be the case.
420+
For example, it is an error to have a range pattern `10..=0`.
421+
422+
Range patterns are *half-open* if they have only an upper or lower bound.
423+
They have the same type as their upper or lower bound.
424+
425+
A half open range with only a lower bound is written as its lower bound followed by `..`.
426+
These range patterns will match on any value greater than or equal to the lower bound.
427+
For example, `1..` will match 1, 9, or 9001, or 9007199254740991 (if it is of an appropriate size), but not 0, and not negative numbers for signed integers.
409428
For an integer the pattern `1..` will match 9, or 9001, or 9007199254740991 (if it is of an appropriate size), but not 0, and not negative numbers for signed integers.
410429
The bounds can be literals or paths that point to constant values.
411430

412-
A half-open range pattern in the style `a..` cannot be used to match within the context of a slice.
431+
A half open range with only an upper bound is written as `..=` followed by its upper bound.
432+
These range patterns will match on any value less than or equal to the upper bound.
433+
For example, `..=10` will match 10, 1, 0, and for signed interger types, all negative values.
413434

414-
A pattern `a..=b` must always have a &le; b.
415-
It is an error to have a range pattern `10..=0`, for example.
435+
Half-open range patterns cannot be used as the top-level pattern for subpatterns in [slice patterns](#slice-patterns).
416436

417-
Range patterns only work on scalar types. The accepted types are:
437+
The bounds is written as one of:
418438

419-
* Integer types (u8, i8, u16, i16, usize, isize, etc.).
420-
* Character types (char).
421-
* Floating point types (f32 and f64).
422-
This is being deprecated and will not be available in a future version of Rust (see [issue #41620](https://github.com/rust-lang/rust/issues/41620)).
439+
* A character, byte, integer, or float literal.
440+
* A `-` followed by an integer or float literal.
441+
* A [path]
442+
443+
If the bounds is written as a path, after macro resolution, the path must resolve to a constant item of the type `char`, an integer type, or a float type.
444+
445+
The type and value of the bounds is dependent upon how it is written out.
446+
If the bounds is a [path], the pattern has the type and value of the [constant] the path resolves to.
447+
If it is a literal, it has the type and value of the corresponding [literal expression].
448+
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.
423449

424450
Examples:
425451

@@ -496,13 +522,19 @@ println!("{}", match 0xfacade {
496522
});
497523
```
498524

499-
Range patterns for (non-`usize` and -`isize`) integer and `char` types are irrefutable when they span the entire set of possible values of a type.
525+
Range patterns for fix-width integer and `char` types are irrefutable when they span the entire set of possible values of a type.
500526
For example, `0u8..=255u8` is irrefutable.
501527
The range of values for an integer type is the closed range from its minimum to maximum value.
502528
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}'`.
503529

530+
Floating point range patterns are deprecated and may be removed in a future Rust release.
531+
See [issue #41620](https://github.com/rust-lang/rust/issues/41620) for more information.
532+
504533
> **Edition Differences**: Before the 2021 edition, closed range patterns may also be written using `...` as an alternative to `..=`, with the same meaning.
505534
535+
> **Note**: Although range patterns use the same syntax as [range expressions], there are no exclusive range patterns.
536+
> That is, neither `x .. y` nor `.. x` are valid range patterns.
537+
506538
## Reference patterns
507539

508540
> **<sup>Syntax</sup>**\
@@ -809,8 +841,13 @@ For example, `x @ A(..) | B(..)` will result in an error that `x` is not bound i
809841

810842
[`Copy`]: special-types-and-traits.md#copy
811843
[IDENTIFIER]: identifiers.md
844+
[constant]: items/constant-items.md
812845
[enums]: items/enumerations.md
813846
[literals]: expressions/literal-expr.md
847+
[literal expression]: expressions/literal-expr.md
848+
[negating]: expressions/operator-expr.md#negation-operators
849+
[path]: expressions/path-expr.md
850+
[range expressions]: expressions/range-expr.md
814851
[structs]: items/structs.md
815852
[tuples]: types/tuple.md
816853
[scrutinee]: glossary.md#scrutinee

0 commit comments

Comments
 (0)