dart-lang / dart-lang/language

[parser/spec] `~`,`-` and `await` inconsistency on function expression literals.

Open
#3,750 2 comments 0 reactions 0 assignees View on GitHub
specification
Dominant language
TeX
Stars
2.9k
Forks
239
Avg merge
2d 18h
Merged PRs (30d)
14

Description

There appears to be an inconsistency wrt unary prefix `-`, `~` and `await` operators on function expression literals between the implementation and DSP.

Consider:

```dart
void main() {
-() => 0;
}
```

```
=== pkg:analyzer (https://pub.dev/packages/analyzer) ===
Parsing succeeded with no errors.
Scan errors: 0
Parse errors: 0
[0-27]
┗━ [0-27]
┣━ [0-4]
┃ ┗━ 'void' [0-4]
┣━ 'main' [5-9]
┗━ [9-27]
┣━ [9-11]
┃ ┣━ '(' [9-10]
┃ ┗━ ')' [10-11]
┗━ [12-27]
┗━ [12-27]
┣━ '{' [12-13]
┣━ [16-25]
┃ ┣━ [16-24]
┃ ┃ ┣━ '-' [16-17]
┃ ┃ ┗━ [17-24]
┃ ┃ ┣━ [17-19]
┃ ┃ ┃ ┣━ '(' [17-18]
┃ ┃ ┃ ┗━ ')' [18-19]
┃ ┃ ┗━ [20-24]
┃ ┃ ┣━ '=>' [20-22]
┃ ┃ ┗━ [23-24]
┃ ┃ ┗━ '0' [23-24]
┃ ┗━ ';' [24-25]
┗━ '}' [26-27]
--------------------------------------------------------------------------------
=== DSP (https://github.com/dart-lang/sdk/blob/master/tools/spec_parser/dart_spec_parser/Dart.g4) dspVersion v0.41 ===
Errors of type 1: [[@8,20:21='=>',<4>,2:6] Bad state: ]
Errors of type 2: []

┗━
┣━
┣━
┃ ┣━
┃ ┃ ┣━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━ 'void'
┃ ┃ ┣━
┃ ┃ ┃ ┗━ 'main'
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┣━ '('
┃ ┃ ┗━ ')'
┃ ┗━
┃ ┗━
┃ ┣━ '{'
┃ ┣━
┃ ┃ ┣━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┣━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┣━
┃ ┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┃ ┗━ '-'
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┣━ '('
┃ ┃ ┃ ┃ ┗━ ')'
┃ ┃ ┃ ┗━ '=>'
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┣━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━ '0'
┃ ┃ ┗━ ';'
┃ ┗━ '}'
┗━ ''
```

and

```dart
final a = ~() => 0;
```

```
=== pkg:analyzer (https://pub.dev/packages/analyzer) ===
Parsing succeeded with no errors.
Scan errors: 0
Parse errors: 0
[0-19]
┗━ [0-19]
┣━ [0-18]
┃ ┣━ 'final' [0-5]
┃ ┗━ [6-18]
┃ ┣━ 'a' [6-7]
┃ ┣━ '=' [8-9]
┃ ┗━ [10-18]
┃ ┣━ '~' [10-11]
┃ ┗━ [11-18]
┃ ┣━ [11-13]
┃ ┃ ┣━ '(' [11-12]
┃ ┃ ┗━ ')' [12-13]
┃ ┗━ [14-18]
┃ ┣━ '=>' [14-16]
┃ ┗━ [17-18]
┃ ┗━ '0' [17-18]
┗━ ';' [18-19]
--------------------------------------------------------------------------------
=== DSP (https://github.com/dart-lang/sdk/blob/master/tools/spec_parser/dart_spec_parser/Dart.g4) dspVersion v0.41 ===
Errors of type 1: [[@6,14:15='=>',<4>,1:14] Bad state: ]
Errors of type 2: []

┗━
┣━
┣━
┃ ┣━ 'final'
┃ ┣━
┃ ┃ ┗━
┃ ┃ ┣━
┃ ┃ ┃ ┗━ 'a'
┃ ┃ ┣━ '='
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┣━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━ '~'
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┣━ '('
┃ ┃ ┗━ ')'
┃ ┣━ '=>'
┃ ┣━ '0'
┃ ┗━ ';'
┗━ ''
```

and

```dart
void a() async {
await () => 0;
}
```

```
=== pkg:analyzer (https://pub.dev/packages/analyzer) ===
Parsing succeeded with no errors.
Scan errors: 0
Parse errors: 0
[0-39]
┗━ [0-39]
┣━ [0-4]
┃ ┗━ 'void' [0-4]
┣━ 'a' [5-6]
┗━ [6-39]
┣━ [6-8]
┃ ┣━ '(' [6-7]
┃ ┗━ ')' [7-8]
┗━ [9-39]
┣━ 'async' [9-14]
┗━ [15-39]
┣━ '{' [15-16]
┣━ [19-33]
┃ ┣━ [19-32]
┃ ┃ ┣━ 'await' [19-24]
┃ ┃ ┗━ [25-32]
┃ ┃ ┣━ [25-27]
┃ ┃ ┃ ┣━ '(' [25-26]
┃ ┃ ┃ ┗━ ')' [26-27]
┃ ┃ ┗━ [28-32]
┃ ┃ ┣━ '=>' [28-30]
┃ ┃ ┗━ [31-32]
┃ ┃ ┗━ '0' [31-32]
┃ ┗━ ';' [32-33]
┗━ '}' [38-39]
--------------------------------------------------------------------------------
=== DSP (https://github.com/dart-lang/sdk/blob/master/tools/spec_parser/dart_spec_parser/Dart.g4) dspVersion v0.41 ===
Errors of type 1: [[@6,19:23='await',<108>,2:2] Bad state: , [@6,19:23='await',<108>,2:2] Bad state: ]
Errors of type 2: []

┗━
┣━
┣━
┃ ┣━
┃ ┃ ┣━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━ 'void'
┃ ┃ ┣━
┃ ┃ ┃ ┗━ 'a'
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┣━ '('
┃ ┃ ┗━ ')'
┃ ┗━
┃ ┣━ 'async'
┃ ┗━
┃ ┣━ '{'
┃ ┣━
┃ ┃ ┣━
┃ ┃ ┃ ┗━
┃ ┃ ┣━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━ 'await'
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┗━
┃ ┃ ┣━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┣━
┃ ┃ ┃ ┃ ┗━
┃ ┃ ┃ ┃ ┣━ '('
┃ ┃ ┃ ┃ ┗━ ')'
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┣━ '=>'
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━
┃ ┃ ┃ ┗━ '0'
┃ ┃ ┗━ ';'
┃ ┗━ '}'
┗━ ''
```

DSP rejects those operators in that position, but those operators are supported by the implementation:

```dart
void main() {
-() => 0;
}

extension on Function {
void operator -() {
print("valid program");
}
}
```

```dart
void main() {
~() => 0;
}

extension on Function {
void operator ~() {
print("valid program");
}
}
```

```dart
void main() async {
await () => 0;
print("valid program");
}
```

Note: something similar can be observed with `!`, i.e. `final a = !() => 0;`, but, AFAIK, ! is never supported as an operator on function expression literals.

Contributor guide

Open the contributing guide

Research direction

Compare the analyzer's parsing of the three function-expression examples with tools/spec_parser/dart_spec_parser/Dart.g4, using the issue's commands and grammar trees as the starting point. Determine the intended handling of -, ~, and await in that position, then align the implementation and DSP so the examples produce consistent parse results.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.