Skip to content

Commit 9e24743

Browse files
authored
Merge pull request #1756 from ehuss/range-to-exclusive-pattern
Rework range pattern rules
2 parents 7d37316 + daa1992 commit 9e24743

File tree

1 file changed

+51
-36
lines changed

1 file changed

+51
-36
lines changed

src/patterns.md

+51-36
Original file line numberDiff line numberDiff line change
@@ -478,10 +478,12 @@ r[patterns.range]
478478
r[patterns.range.syntax]
479479
> **<sup>Syntax</sup>**\
480480
> _RangePattern_ :\
481-
> &nbsp;&nbsp; &nbsp;&nbsp; _RangeInclusivePattern_\
481+
> &nbsp;&nbsp; &nbsp;&nbsp; _RangeExclusivePattern_\
482+
> &nbsp;&nbsp; | _RangeInclusivePattern_\
482483
> &nbsp;&nbsp; | _RangeFromPattern_\
484+
> &nbsp;&nbsp; | _RangeToExclusivePattern_\
483485
> &nbsp;&nbsp; | _RangeToInclusivePattern_\
484-
> &nbsp;&nbsp; | _ObsoleteRangePattern_
486+
> &nbsp;&nbsp; | _ObsoleteRangePattern_[^obsolete-range-edition]
485487
>
486488
> _RangeExclusivePattern_ :\
487489
> &nbsp;&nbsp; &nbsp;&nbsp; _RangePatternBound_ `..` _RangePatternBound_
@@ -492,6 +494,9 @@ r[patterns.range.syntax]
492494
> _RangeFromPattern_ :\
493495
> &nbsp;&nbsp; &nbsp;&nbsp; _RangePatternBound_ `..`
494496
>
497+
> _RangeToExclusivePattern_ :\
498+
> &nbsp;&nbsp; &nbsp;&nbsp; `..` _RangePatternBound_
499+
>
495500
> _RangeToInclusivePattern_ :\
496501
> &nbsp;&nbsp; &nbsp;&nbsp; `..=` _RangePatternBound_
497502
>
@@ -504,69 +509,75 @@ r[patterns.range.syntax]
504509
> &nbsp;&nbsp; | `-`<sup>?</sup> [INTEGER_LITERAL]\
505510
> &nbsp;&nbsp; | `-`<sup>?</sup> [FLOAT_LITERAL]\
506511
> &nbsp;&nbsp; | [_PathExpression_]
512+
>
513+
> [^obsolete-range-edition]: The _ObsoleteRangePattern_ syntax has been removed in the 2021 edition.
507514
508515
r[patterns.range.intro]
509516
*Range patterns* match scalar values within the range defined by their bounds.
510-
They comprise a *sigil* (one of `..`, `..=`, or `...`) and a bound on one or both sides.
517+
They comprise a *sigil* (`..` or `..=`) and a bound on one or both sides.
511518

512-
r[patterns.range.lower-bound]
513-
A bound on the left of the sigil is a *lower bound*.
519+
A bound on the left of the sigil is called a *lower bound*.
520+
A bound on the right is called an *upper bound*.
514521

515-
r[patterns.range.upper-bound]
516-
A bound on the right is an *upper bound*.
522+
r[patterns.range.exclusive]
523+
The *exclusive range pattern* matches all values from the lower bound up to, but not including the upper bound.
524+
It is written as its lower bound, followed by `..`, followed by the upper bound.
517525

518-
r[patterns.range.closed]
519-
A range pattern with both a lower and upper bound will match all values between and including both of its bounds.
520-
It is written as its lower bound, followed by `..` for end-exclusive or `..=` for end-inclusive, followed by its upper bound.
526+
For example, a pattern `'m'..'p'` will match only `'m'`, `'n'` and `'o'`, specifically **not** including `'p'`.
521527

522-
r[patterns.range.type]
523-
The type of the range pattern is the type unification of its upper and lower bounds.
528+
r[patterns.range.inclusive]
529+
The *inclusive range pattern* matches all values from the lower bound up to and including the upper bound.
530+
It is written as its lower bound, followed by `..=`, followed by the upper bound.
524531

525532
For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, `'o'`, and `'p'`.
526-
Similarly, `'m'..'p'` will match only `'m'`, `'n'` and `'o'`, specifically **not** including `'p'`.
533+
534+
r[patterns.range.from]
535+
The *from range pattern* matches all values greater than or equal to the lower bound.
536+
It is written as its lower bound followed by `..`.
537+
538+
For example, `1..` will match any integer greater than or equal to 1, such as 1, 9, or 9001, or 9007199254740991 (if it is of an appropriate size), but not 0, and not negative numbers for signed integers.
539+
540+
r[patterns.range.to-exclusive]
541+
The *to exclusive range pattern* matches all values less than the upper bound.
542+
It is written as `..` followed by the upper bound.
543+
544+
For example, `..10` will match any integer less than 10, such as 9, 1, 0, and for signed integer types, all negative values.
545+
546+
r[patterns.range.to-inclusive]
547+
The *to inclusive range pattern* matches all values less than or equal to the upper bound.
548+
It is written as `..=` followed by the upper bound.
549+
550+
For example, `..=10` will match any integer less than or equal to 10, such as 10, 1, 0, and for signed integer types, all negative values.
527551

528552
r[patterns.range.constraint-less-than]
529553
The lower bound cannot be greater than the upper bound.
530554
That is, in `a..=b`, a &le; b must be the case.
531555
For example, it is an error to have a range pattern `10..=0`.
532556

533-
r[patterns.range.open-below]
534-
A range pattern with only a lower bound will match any value greater than or equal to the lower bound.
535-
It is written as its lower bound followed by `..`, and has the same type as its lower bound.
536-
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.
537-
538-
r[patterns.range.open-above]
539-
A range pattern with only an upper bound matches any value less than or equal to the upper bound.
540-
It is written as `..=` followed by its upper bound, and has the same type as its upper bound.
541-
For example, `..=10` will match 10, 1, 0, and for signed integer types, all negative values.
542-
543-
r[patterns.range.constraint-slice]
544-
Range patterns with only one bound cannot be used as the top-level pattern for subpatterns in [slice patterns](#slice-patterns).
545-
546557
r[patterns.range.bound]
547-
The bounds is written as one of:
558+
A bound is written as one of:
548559

549560
* A character, byte, integer, or float literal.
550561
* A `-` followed by an integer or float literal.
551562
* A [path]
552563

553564
r[patterns.range.constraint-bound-path]
554-
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.
565+
If a bound 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.
555566

556-
r[patterns.range.value]
557-
The type and value of the bounds is dependent upon how it is written out.
567+
r[patterns.range.type]
568+
The range pattern matches the type of its upper and lower bounds, which must be the same type.
558569

559570
r[patterns.range.path-value]
560-
If the bounds is a [path], the pattern has the type and value of the [constant] the path resolves to.
561-
562-
r[patterns.range.float-restriction]
563-
For float range patterns, the constant may not be a `NaN`.
571+
If a bound is a [path], the bound matches the type and has the value of the [constant] the path resolves to.
564572

565573
r[patterns.range.literal-value]
566-
If it is a literal, it has the type and value of the corresponding [literal expression].
574+
If a bound is a literal, the bound matches the type and has the value of the corresponding [literal expression].
567575

568576
r[patterns.range.negation]
569-
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.
577+
If a bound is a literal preceded by a `-`, the bound matches the same type as the corresponding [literal expression] and has the value of [negating] the value of the corresponding literal expression.
578+
579+
r[patterns.range.float-restriction]
580+
For float range patterns, the constant may not be a `NaN`.
570581

571582
Examples:
572583

@@ -653,6 +664,10 @@ The range of values for an integer type is the closed range from its minimum to
653664
r[patterns.range.refutable-char]
654665
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}'`.
655666

667+
r[patterns.range.constraint-slice]
668+
_RangeFromPattern_ cannot be used as a top-level pattern for subpatterns in [slice patterns](#slice-patterns).
669+
For example, the pattern `[1.., _]` is not a valid pattern.
670+
656671
r[patterns.range.edition2021]
657672
> **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.
658673

0 commit comments

Comments
 (0)