dart-lang / dart-lang/language
Meta: Small and useful features collection
- Dominant language
- TeX
- Stars
- 2.9k
- Forks
- 239
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 14
Description
This meta-issue collects a potpourri of small Dart language enhancements that will thrill users and not cost too much to implement.
We want to choose a subset of these to implement in the next quarter(s).
This issue is for discussion of which of these features offer the most bang-per-buck, and whether there are other low-hanging fruity features to add.
To qualify, the feature should be well-defined enough that it doesn't require significant further design work (so either very trivial or already designed to a large degree), it should be localized enough that it's unlikely to interfere with other language features, and it should not involve the more complicated parts of the Dart semantics (like the type system). If it can be implemented entirely in the front-end (aka, it's syntactic sugar), then that's a great advantage.
The initial features here are mainly syntactical niceties (syntactic sugar) and features which are largely self-contained.
Go vote for your favorite feature by +1'ing its issue.
- [x] Unnamed `library;` declaration ([#1073][])
- [ ] Shorthand for `import`/`export` URIs ([#649][])
- [ ] Parentheses around element expression ([#780][])
- [x] Null aware element expression ([#323][])
- [ ] Unparanthesized function expression parameter ([#320][])
- [x] Named arguments everywhere ([#1072][])
- [ ] Suffix `await` ([#25][])
- [ ] `&&=` and `||=` assignment operators ([#122][])
- [x] `>>>` operator ([#120][])
- [ ] Setter named symbol literals ([#301][])
- [x] Number Digit Separators ([#2][])
- [ ] Binary integer literals ([#581][])
- [ ] Character code constants ([#886][])
- [x] Allow generic function types as type arguments ([#496][])
- [x] Generic metadata constructors ([#1297][])
(See [issues sorted by up-votes](https://github.com/dart-lang/language/issues?q=is%3Aissue+is%3Aopen+label%3Asmall-feature+-label%3Ameta+sort%3Areactions-%2B1-desc+)).
A rough summary of these features is included below.
## Unnamed Library Declarations ([#1073][])
Allow `library;` to be a library declaration with an empty name.
This is equivalent to no library declaration, but it provides a place to hang library annotations. Currently you have to give a library a *name* in order to, say, deprecate it, which seems (and really is) unnecessary.
Can also, over time, be used to move library dartdoc away from the import section.
## Import/Export Shorthand Syntax ([#649][])
Allow import shorthands like:
```dart
import dart:async; // Same as "dart:async"
import test; // Same as "package:test/test.dart"
import collection:equality // Same as "package:collection/equality.dart"
```
We'll allow a sequence of some non-space, non-`;` characters (potentially only `.`, `/`, `:`, letters and digits) to act as a a shorthand for the full URI. We still accept the full URI for cases that contain other characters.
There might be some third-party tools which parse imports using RegExps. If so, those will need to change.
## Parenthesized Element Expressions ([#780][])
Allow
> `(` *elementExpression* `)`
as an *elementExpression*. That allows
```dart
var list = [if (t1) (if (t2) e1) else (if (t3) e2)];
```
which is otherwise not expressible to express without introducing artificial intermediates because the `else` would bind to the nearest `if`.
If parsing to an AST, grouping parentheses can be ignored, but the formatter needs to be aware of them.
## Null Aware Element Expressions ([#323][])
Allow `? expression` as an element expression, so `[?x]` is equivalent to `[if (x != null) x]`, but only evaluating `x` once.
This is a sweet spot of null-awareness, without too much complexity, and it fits well with `…?`.
## Unparenthesized Function Parameter ([#320][])
Allow `(foo) => expr` to be written as `foo => expr`. It only applies to a single untyped argument of an arrow-syntax function expression.
Might not be worth it compared to just having `=> expr` have an implicit parameter of `(it)`.
## Named Arguments Everywhere ([#1072][])
Allow named arguments to occur before positional arguments in an argument list.
Currently you cannot do `expectAsync(count: 2, () { … })`, but have to put the `count` argument after the large function body where it's harder to find.
By allowing named arguments before positional arguments, this becomes possible. Evaluation order of arguments is still left-to-right, so it cannot simply be desugared away by moving the argument. The front end can introduce `let` constructs to force the order of evaluation and then pass the resulting values in the same order as before.
## Suffix Await ([#25][])
Allow `e.await` in `async` functions to mean the same as `(await e)`.
Since `await` as a reserved word in those functions, this will not conflict with any existing code.
It reads much better in long chains of operations because it doesn't need parentheses.
It will also have to work with `e?.await`, `e..await` and `e?..await`, and generally look like a getter. Maybe only allow it on expressions of type `FutureOr` and `Future`.
Can be desugared in the front-end.
## `&&=` and `||=` Short-circuit Assignments ([#122][])
Allow `x &&= y` to mean `x ? x = y : false` (aka. `x && x = y`) and `x ||= y` to mean `x ? true : x = y;` (aka. `x || x = y`), where `x` is only evaluated once as usual.
These can be desugared entirely in the front-end.
## Triple Shift ([#120][])
Implement `>>>` as a user-declarable operator with the same precedence as `>>`.
This includes allowing `#>>>` and `const Symbol(">>>")` as symbols.
(We can then also implement `int.>>>` when possible).
Might need minimal backend support as well as front-end changes.
## Setter-Named Symbol Literals ([#301][])
Allow `#foo=` to be a symbol literal for the setter name `foo=`. Must work for private symbols too.
## Number Digit Separators ([#2][])
Allow one or more `_` characters between digits in number literals. The `_`s have no effect, they are ignored when figuring out the numeric value of the literal. They work for decimal, hexadecimal and floating point literals, in the latter case also in the exponent section, as long as they are flanked by *digits* on both sides (where hexadecimal literal digits include the letters `a`..`f`, and all other literals don't).
There is no change to `int.parse` or similar functions. Anyone needing to parse numbers containing `_` characters can remove them first using `String.replaceAll`.
Can happen entirely in the front-end.
## Binary Integer Literals
Allow binary integers similar to hexadecimal integers. That would be: `0b1001` for 9.
It's just a new way of writing an integer literal, it can happen entirely in the front-end.
(It's unlikely that we'll want a more general any-radix integer functionality, so this should not conflict with any other feature).
## Character Code Constants ([#886][])
Allow `c"x"` as a way to write 0x79 (it's an *integer literal*). The string must contain exactly one code point, so it's a constant expression otherwise equal to `"x".runes.first`.
Can be implemented entirely in the front-end.
## Allow generic function types as type arguments ([#496][]);
Currently Dart does not allow a generic function type, like `T Function(T)` to be used as a type argument.
This restriction was introduced as a precautionary limit on the type system, but it has been hit by user code, and there is no easy workaround other than using `Function` and having more unsafe code.
The issue is amplified by they type inference happily inferring a generic type argument, and then the compiler rejects it immediately after.
We hope that simply removing the check will be sufficient, and that no back-end code is affected.
## Generic Metadata ([#1297][])
Allow const constructor invocations in metadata to have type arguments.
```
@Foo>()
int bar = 0;
```
This is currently not allowed by the grammar. There should be on issues with it.
[#2]: https://github.com/dart-lang/language/issues/2 "Number Digit Separator"
[#25]: https://github.com/dart-lang/language/issues/25 "Suffix await"
[#122]: https://github.com/dart-lang/language/issues/122 "&&= and ||="
[#120]: https://github.com/dart-lang/language/issues/120 "Triple Shift"
[#301]: https://github.com/dart-lang/language/issues/301 "Setter Symbol Literals"
[#320]: https://github.com/dart-lang/language/issues/320 "Unparenthesized Single Parameter"
[#323]: https://github.com/dart-lang/language/issues/323 "Null Aware Elements"
[#496]: https://github.com/dart-lang/language/issues/496 "Generic function types as type arguments"
[#581]: https://github.com/dart-lang/language/issues/581 "Binary Integer Literals"
[#649]: https://github.com/dart-lang/language/issues/649 "Import Uri Shorthand"
[#780]: https://github.com/dart-lang/language/issues/780 "Paranthesized Elements"
[#886]: https://github.com/dart-lang/language/issues/886 "Character Code Constants"
[#1072]: https://github.com/dart-lang/language/issues/1072 "Named Arguments Anywhere"
[#1073]: https://github.com/dart-lang/language/issues/1073 "Unnamed Library Declarations"
[#1297]: https://github.com/dart-lang/language/issues/1297 "Generic Metadata"
Contributor guide
Research direction
Start by reviewing the linked feature issues, especially the proposals listed in this meta-issue, and compare their design maturity and implementation scope. This issue has no code entry point or test named; the work is complete when a well-defined subset is selected for implementation or an additional low-hanging feature is specified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- dart
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100