Skip to content

Commit 0760390

Browse files
committed
[patterns] Avoid unbounded lookahead to distinguish switches.
Also re-introduce rule to always make "_" non-binding.
1 parent 0591e81 commit 0760390

File tree

1 file changed

+51
-3
lines changed

1 file changed

+51
-3
lines changed

working/0546-patterns/patterns-feature-specification.md

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Author: Bob Nystrom
44

55
Status: In progress
66

7-
Version 1.2 (see [CHANGELOG](#CHANGELOG) at end)
7+
Version 1.3 (see [CHANGELOG](#CHANGELOG) at end)
88

99
## Summary
1010

@@ -527,6 +527,35 @@ Over half of the switch cases in a large corpus of packages contain either a
527527
single return statement or an assignment followed by a break so there is some
528528
evidence this will be useful.
529529

530+
#### Expression statement ambiguity
531+
532+
Thanks to expression statements, a switch expression could appear in the same
533+
position as a switch statement. This isn't technically ambiguous, but requires
534+
unbounded lookahead to tell if a switch in statement position is a statement or
535+
expression.
536+
537+
```dart
538+
main() {
539+
switch (some(extremely, long, expression, here)) {
540+
case Some(Quite(var long, var pattern)) => expression();
541+
};
542+
543+
switch (some(extremely, long, expression, here)) {
544+
case Some(Quite(var long, var pattern)) : statement();
545+
}
546+
}
547+
```
548+
549+
To avoid that, we disallow a switch expression from appearing at the beginning
550+
of an expression statement. This is similar to existing restrictions on map
551+
literals appearing in expression statements. In the rare case where a user
552+
really wants one there, they can parenthesize it.
553+
554+
**TODO: If we change switch expressions [to use `:` instead of `=>`][2126] then
555+
there will be an actual ambiguity. In that case, reword the above section.**
556+
557+
[2126]: https://github.com/dart-lang/language/issues/2126
558+
530559
### If-case statement
531560

532561
Often you want to conditionally match and destructure some data, but you only
@@ -1401,8 +1430,17 @@ It is a compile-time error if the type of an expression in a guard clause is not
14011430
### Variables and scope
14021431
14031432
Patterns often exist to introduce new bindings. Type patterns introduce type
1404-
variables and other patterns introduce normal variables. The variables a
1405-
patterns binds depend on what kind of pattern it is:
1433+
variables and other patterns introduce normal variables.
1434+
1435+
Consistent with wildcard patterns, any time a pattern contains an identifier
1436+
that would introduce a binding, no binding is created if the identifier is `_`.
1437+
1438+
*We always treat `_` as non-binding in patterns. It's sometimes useful to have
1439+
patterns that aren't wildcards but still don't want to bind. For example, a
1440+
variable matcher with a type annotation and `_` as its name is a useful pattern
1441+
for testing the type of a value.*
1442+
1443+
The variables a patterns binds depend on what kind of pattern it is:
14061444
14071445
* **Type pattern**: Type argument patterns (i.e. `typePattern` in the grammar)
14081446
that appear anywhere in some other pattern introduce new *type* variables
@@ -1788,6 +1826,16 @@ main() {
17881826

17891827
## Changelog
17901828

1829+
### 1.3
1830+
1831+
- Avoid unbounded lookahead with switch expression in an expression statement
1832+
([#2138][]).
1833+
1834+
- Re-introduce rule that `_` is non-binding in all patterns, not just
1835+
wildcards.
1836+
1837+
[#2138]: https://github.com/dart-lang/language/issues/2138
1838+
17911839
### 1.2
17921840

17931841
- Add a shorthand for destructuring a named record field to a variable with

0 commit comments

Comments
 (0)