@@ -10,7 +10,7 @@ Experiment flag: null-aware-elements
10
10
11
11
## Introduction
12
12
13
- In Dart 2.3, we added [ several syntax new features] [ unified ] for use inside
13
+ In Dart 2.3, we added [ several new syntax features] [ unified ] for use inside
14
14
collection literals. You can use ` ... ` to spread the contents of one collection
15
15
into another, and ` if ` and ` for ` to perform branching and looping control flow
16
16
while generating elements.
@@ -62,7 +62,7 @@ have null-aware spreads, but not null-aware single values.
62
62
63
63
This proposal remedies that by adding * null-aware elements* . Using Lorenzen's
64
64
suggested syntax, inside a collection literal, a ` ? ` followed by an expression
65
- includes the value if it's not ` null ` or discards the ` null ` otherwise:
65
+ includes the value if it's not ` null ` and discards the ` null ` otherwise:
66
66
67
67
``` dart
68
68
void printThree(String? a, String? b, String? c) {
@@ -142,8 +142,8 @@ general-purpose feature.
142
142
143
143
It's also certainly the case that my simple analysis didn't catch many other
144
144
workarounds that users are using to deal with ` null ` . (I did look for uses of
145
- ` if-case ` and ` .whereNotNull() ` that seemed like could become null-aware
146
- elements but only found a handful.)
145
+ ` if-case ` , ` .whereNotNull() ` , and ` .nonNulls ` that seemed like could become
146
+ null-aware elements but only found a handful.)
147
147
148
148
This suggests that if we're to support this feature at all, we should support
149
149
it for map entries too. The syntax options, assuming we want to stick with a
@@ -322,7 +322,7 @@ otherNullableThing`.*
322
322
expressions, null-aware operators, and null-check patterns. However, I don't
323
323
believe there is any ambiguity in this new syntax. The preceding token will
324
324
usually be ` , ` , ` [ ` , ` { ` , or ` : ` , none of which can appear before ` ? ` in any
325
- form that uses that character. The ` ? ` may also appear before ` ) ` after the
325
+ form that uses that character. The ` ? ` may also appear after ` ) ` after the
326
326
header of an ` if ` or ` for ` element, or after ` else ` , but those are also not
327
327
ambiguous.*
328
328
@@ -356,50 +356,53 @@ To infer the type of `element` in context `P`:
356
356
357
357
* If ` element ` is a null-aware ` expressionElement ` with expression ` e1 ` :
358
358
359
- * If ` P ` is ` ? ` :
359
+ * If ` P ` is ` _ ` (the unknown context) :
360
360
361
- * Let ` u ` be the inferred type of the expression ` e1 ` in context ` ? ` .
361
+ * Let ` U ` be the inferred type of the expression ` e1 ` in context ` _ ` .
362
362
363
363
* Else, ` P ` is ` Set<Ps> ` :
364
364
365
- * Let ` u ` be the inferred type of the expression ` e1 ` in context ` Ps ` .
365
+ * Let ` U ` be the inferred type of the expression ` e1 ` in context
366
+ ` Ps? ` . * The expression has a nullable context type because it may
367
+ safely evaluate to ` null ` even when the surrounding set doesn't
368
+ allow that because the ` ? ` will discard a ` null ` entry.*
366
369
367
- * The inferred set element type is ** NonNull** (` u ` ). * The value added to
370
+ * The inferred set element type is ** NonNull** (` U ` ). * The value added to
368
371
the set will never be ` null ` .*
369
372
370
373
* If ` element ` is a null-aware ` mapElement ` with entry ` ek: ev ` :
371
374
372
- * If ` P ` is ` ? ` then the inferred key and value types of ` element ` are:
375
+ * If ` P ` is ` _ ` then the inferred key and value types of ` element ` are:
373
376
374
- * Let ` uk ` be the inferred type of ` ek ` in context ` ? ` .
377
+ * Let ` Uk ` be the inferred type of ` ek ` in context ` _ ` .
375
378
376
379
* If ` element ` is a key null-aware element then the inferred key
377
- element type is ** NonNull** (` uk ` ). * The entry added to the map will
380
+ element type is ** NonNull** (` Uk ` ). * The entry added to the map will
378
381
never have a ` null ` key.*
379
382
380
- * Else the inferred key element type is ` uk ` . * The whole element is
383
+ * Else the inferred key element type is ` Uk ` . * The whole element is
381
384
null-aware, but the key part is not, so it is inferred as normal.*
382
385
383
- * Let ` uv ` be the inferred type of ` ev ` in context ` ? ` .
386
+ * Let ` Uv ` be the inferred type of ` ev ` in context ` _ ` .
384
387
385
388
* If ` element ` is a value null-aware element then the inferred value
386
- element type is ** NonNull** (` uv ` ). * The entry added to the map will
389
+ element type is ** NonNull** (` Uv ` ). * The entry added to the map will
387
390
never have a ` null ` value.*
388
391
389
- * Else the inferred value element type is ` uv ` . * The whole element is
392
+ * Else the inferred value element type is ` Uv ` . * The whole element is
390
393
null-aware, but the value part is not, so it is inferred as normal.*
391
394
392
395
* If ` P ` is ` Map<Pk, Pv> ` then the inferred key and value types of
393
396
` element ` are:
394
397
395
398
* If ` element ` is a key null-aware element then:
396
399
397
- * Let ` uk ` be the inferred type of ` ek ` in context ` Pk? ` . * The key
400
+ * Let ` Uk ` be the inferred type of ` ek ` in context ` Pk? ` . * The key
398
401
expression has a nullable context type because it may safely
399
402
evaluate to ` null ` even when the surrounding map doesn't allow
400
403
that because the ` ? ` will discard a ` null ` entry.*
401
404
402
- * The inferred key element type is ** NonNull** (` uk ` ). * The entry
405
+ * The inferred key element type is ** NonNull** (` Uk ` ). * The entry
403
406
added to the map will never have a ` null ` key.*
404
407
405
408
* Else the inferred key element type is the inferred type of ` ek ` in
@@ -408,12 +411,12 @@ To infer the type of `element` in context `P`:
408
411
409
412
* If ` element ` is a value null-aware element then:
410
413
411
- * Let ` uv ` be the inferred type of ` ev ` in context ` Pv? ` . * The
414
+ * Let ` Uv ` be the inferred type of ` ev ` in context ` Pv? ` . * The
412
415
value expression has a nullable context type because it may
413
416
safely evaluate to ` null ` even when the surrounding map doesn't
414
417
allow that because the ` ? ` will discard a ` null ` entry.*
415
418
416
- * The inferred value element type is ** NonNull** (` uv ` ). * The entry
419
+ * The inferred value element type is ** NonNull** (` Uv ` ). * The entry
417
420
added to the map will never have a ` null ` value.*
418
421
419
422
* Else the inferred value element type is the inferred type of ` ev ` in
@@ -430,27 +433,32 @@ null-aware part because `null` won't propagate out.*
430
433
431
434
Likewise, with list literals, we add a clause to handle a null-aware expression.
432
435
433
- To infer the type of ` element ` in context ` P ` (which may be ` ? ` ) :
436
+ To infer the type of ` element ` in context ` P ` :
434
437
435
438
* If ` element ` is null-aware ` expressionElement ` with expression ` e1 ` :
436
439
437
- * Let ` u ` be the inferred type of ` element ` in context ` P? ` . * The
438
- expression has a nullable context type because it may safely evaluate to
439
- ` null ` even when the surrounding list doesn't allow that because the ` ? `
440
- will discard a ` null ` entry.*
440
+ * If ` P ` is ` _ ` :
441
+
442
+ * Let ` U ` be the inferred type of the expression ` e1 ` in context ` _ ` .
443
+
444
+ * Else, ` P ` is ` List<Ps> ` :
445
+
446
+ * Let ` U ` be the inferred type of the expression ` e1 ` in context
447
+ ` Ps? ` . * The expression has a nullable context type because it may
448
+ safely evaluate to ` null ` even when the surrounding set doesn't
449
+ allow that because the ` ? ` will discard a ` null ` entry.*
441
450
442
- * The inferred list element type of ` element ` is ** NonNull** (` u ` ). * The
443
- value added to the map will never be ` null ` .*
451
+ * The inferred list element type is ** NonNull** (` U ` ). * The value added to
452
+ the list will never be ` null ` .*
444
453
445
454
### Constants
446
455
447
- A null-aware ` expressionElement ` or ` mapElement ` is constant or potentially
448
- constant if its inner expression or map entry is constant or potentially
449
- constant, respectively.
456
+ A null-aware ` expressionElement ` or ` mapElement ` is constant if its inner
457
+ expression or map entry is constant.
450
458
451
- ## Dynamic semantics
459
+ ## Runtime semantics
452
460
453
- The dynamic semantics of collection literals [ are
461
+ The runtime semantics of collection literals [ are
454
462
defined] [ unified-dynamic-element ] in terms of recursively building up a * result*
455
463
sequence of values (list or set) or map entries (map). For each kind of
456
464
` element ` , there is specification for how that element adds to the result. We
@@ -525,7 +533,7 @@ use instead:
525
533
526
534
[
527
535
nullableFoo,
528
- ].whereNotNull().toList() ;
536
+ ].nonNulls ;
529
537
```
530
538
531
539
If any of these patterns can be reliably detected through static analysis, then
0 commit comments