Skip to content

Commit 4ea7c5d

Browse files
authored
Merge pull request #1274 from Havvy/half-open-ranges
Document Half Open Range Patterns + Improve Range Patterns in General
2 parents 0276e07 + 6c8431f commit 4ea7c5d

File tree

1 file changed

+50
-14
lines changed

1 file changed

+50
-14
lines changed

src/patterns.md

+50-14
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,8 @@ match tuple {
388388
>       _RangePatternBound_ `..=` _RangePatternBound_
389389
>
390390
> _HalfOpenRangePattern_ :\
391-
>    | _RangePatternBound_ `..`
391+
>       _RangePatternBound_ `..`
392+
>    | `..=` _RangePatternBound_
392393
>
393394
> _ObsoleteRangePattern_ :\
394395
>    _RangePatternBound_ `...` _RangePatternBound_
@@ -400,26 +401,50 @@ 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'`.
409-
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.
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.
410428
The bounds can be literals or paths that point to constant values.
411429

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

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.
434+
Half-open range patterns cannot be used as the top-level pattern for subpatterns in [slice patterns](#slice-patterns).
416435

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

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)).
438+
* A character, byte, integer, or float literal.
439+
* A `-` followed by an integer or float literal.
440+
* A [path]
441+
442+
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.
443+
444+
The type and value of the bounds is dependent upon how it is written out.
445+
If the bounds is a [path], the pattern has the type and value of the [constant] the path resolves to.
446+
If it is a literal, it has the type and value of the corresponding [literal expression].
447+
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.
423448

424449
Examples:
425450

@@ -496,13 +521,19 @@ println!("{}", match 0xfacade {
496521
});
497522
```
498523

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.
524+
Range patterns for fix-width integer and `char` types are irrefutable when they span the entire set of possible values of a type.
500525
For example, `0u8..=255u8` is irrefutable.
501526
The range of values for an integer type is the closed range from its minimum to maximum value.
502527
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}'`.
503528

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

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

810841
[`Copy`]: special-types-and-traits.md#copy
811842
[IDENTIFIER]: identifiers.md
843+
[constant]: items/constant-items.md
812844
[enums]: items/enumerations.md
813845
[literals]: expressions/literal-expr.md
846+
[literal expression]: expressions/literal-expr.md
847+
[negating]: expressions/operator-expr.md#negation-operators
848+
[path]: expressions/path-expr.md
849+
[range expressions]: expressions/range-expr.md
814850
[structs]: items/structs.md
815851
[tuples]: types/tuple.md
816852
[scrutinee]: glossary.md#scrutinee

0 commit comments

Comments
 (0)