1
1
# Augmentation Libraries
2
2
3
3
4
- Version: 1.11 (see [ Changelog] ( #Changelog ) at end)
4
+ Version: 1.12 (see [ Changelog] ( #Changelog ) at end)
5
5
6
6
Augmentation libraries allow splitting a Dart library into files. Unlike part
7
7
files, each augmentation has its [ own imports] [ part imports ] and top-level
@@ -316,9 +316,6 @@ augmented, but it follows generally the same rules as any normal identifier:
316
316
initializer if the member being augmented is not a field with an
317
317
initializer.
318
318
319
- **TODO:** Define the behavior when a field is augmented by a getter or
320
- setter, and then later again by a field.
321
-
322
319
* **Augmenting functions**: When augmenting a function, `augment super` refers
323
320
to the augmented function. Tear offs are allowed.
324
321
@@ -441,12 +438,12 @@ this interact with type checking calls to the function?**
441
438
442
439
### Augmenting variables, getters, and setters
443
440
444
- Augmentations on variables, getters, and setters are more complex because the
445
- language treats those as [ mostly interchangeable] [ uniform ] . We want to preserve
446
- that flexibility in augmentations. For example, an augmentation might want to
447
- wrap access to a variable in an augmenting getter. Or an augmentation may want
448
- to fill in the body of an unimplemented getter by using a backing variable
449
- declaration .
441
+ While the language treats variables, getters, and setters as
442
+ [ mostly interchangeable] [ uniform ] , within augmentation libraries we do not allow
443
+ augmenting getters and setters with variables. Since augmentations are tightly
444
+ coupled to the libraries they augment, this restriction has minimal impact, and
445
+ it does not greatly affect the ability of a library to change a field to a
446
+ getter/setter pair or vice-versa .
450
447
451
448
[ uniform ] : https://en.wikipedia.org/wiki/Uniform_access_principle
452
449
@@ -489,23 +486,53 @@ More specifically:
489
486
non-final variable in the main library. Inside the augmenting setter, an
490
487
` augment super = ` expression invokes the original setter.
491
488
492
- * ** Augmenting a getter and/or setter with a variable:** A variable in an
493
- augmentation library can augment a getter in the main library. A non-final
494
- variable can augment a setter as well. The implicit getter and setter
495
- defined by the augmenting variable replace the getter and setter in the main
496
- library.
497
-
498
- * ** Augmenting a variable with a variable:** The original storage location is
499
- discarded and the original implicit getter and setter are replaced with the
500
- new implicit ones. * In most cases, the distinction of which implicit
501
- getter/setter is kept is not visible. But if augmenting a ` late ` variable
502
- with a non-` late ` one or vice versa, the bodies behave differently in
503
- user-visible ways.*
504
-
505
- The original initializer expression is replaced with the augmenting
506
- variable's initializer if it has one. The augmenting initializer may use an
489
+ * ** Augmenting a getter and/or setter with a variable:** This is a
490
+ compile-time error in all cases. We may decide in the future to allow
491
+ augmenting abstract or external getters and setters with variables, but for
492
+ now you can instead use the following workaround:
493
+
494
+ - Add a new field.
495
+ - Augment the getter and/or setter to delegate to that field.
496
+
497
+ If a concrete variable is augmented by a getter or setter, you ** can** still
498
+ augment the variable, as you are only augmenting the initializer. This is
499
+ not considered to be augmenting the augmenting getter or setter, since those
500
+ are not actually altered.
501
+
502
+ The reason for this is that whether a member declaration is a field versus a
503
+ getter/setter is a visible property of the declaration: It determines
504
+ whether the member can be initialized in a constructor initializer list. It
505
+ is also a visible distinction when introspecting on a program with the
506
+ analyzer, macros, or mirrors.
507
+
508
+ When a declaration is augmented, we don't want the augmentation to be able
509
+ to change any of the known properties of the existing member being
510
+ augmented. For example, we don't allow you to augment a method with a getter
511
+ that returns a function. Augmenting a getter/setter pair with a field would
512
+ change the "can be used in a constructor initializer" property, so we forbid
513
+ it. Augmenting a field with a getter/setter doesn't change that property so
514
+ it is allowed.
515
+
516
+ * ** Augmenting a variable with a variable:** When augmenting a variable with
517
+ a variable, the behavior differs depending on whether the original variable
518
+ has a concrete implementation or not. Note that this concrete implementation
519
+ could be one that is filled in by a compiler or other external source, if
520
+ the declaration is marked ` external ` .
521
+
522
+ If the variable being augmented _ does not_ have a concrete implementation,
523
+ then it gets one from the augmenting variable. This includes the backing
524
+ store, the implicit getter and setter, as well as the initializer if
525
+ present.
526
+
527
+ If the variable being augmented _ does_ ** _ have a concrete implementation,
528
+ then only the initializer has any meaning, and it replaces the original
529
+ initializer. In this case the augmenting initializer may use an
507
530
` augment super ` expression which executes the original initializer
508
- expression when evaluated.
531
+ expression when evaluated. Augmenting a concrete field with a field does not
532
+ affect its backing store, getter, or setter.
533
+
534
+ The ` late ` property of a variable must always be consistent between the
535
+ augmented variable and its augmenting variables.
509
536
510
537
If the variable declaration in the original library does not have a type
511
538
annotation, then the type is inferred only using the original library's
@@ -519,6 +546,11 @@ It is a compile-time error if:
519
546
520
547
* The original and augmenting declarations do not have the same type.
521
548
549
+ * An augmenting declaration uses ` augment super ` when the original declaration
550
+ has no concrete implementation. Note that all external declarations are
551
+ assumed to have an implementation provided by another external source, and
552
+ they will throw a runtime exception when called if not.
553
+
522
554
* An augmenting initializer uses ` augment super ` and the original declaration
523
555
is not a variable with an initializer.
524
556
@@ -529,11 +561,11 @@ It is a compile-time error if:
529
561
* A non-final variable is augmented with a final variable. We don't want to
530
562
leave the original setter in a weird state.
531
563
532
- * A non- ` late ` augmenting instance variable initializer contains `augment
533
- super ` and the variable being augmented is ` late ` . *Initializers for ` late`
534
- instance variables have access to ` this ` while non- ` late ` variables do not .
535
- This means a ` late ` variable's initializer can't be called from a non- ` late `
536
- variable's initializer. *
564
+ * A ` late ` variable is augmented with a non- ` late ` variable.
565
+
566
+ * A non- ` late ` variable is augmented with a ` late ` variable .
567
+
568
+ * A concrete getter or setter are augmented by a variable.
537
569
538
570
### Augmenting enum values
539
571
@@ -928,11 +960,15 @@ language and our tools.
928
960
929
961
## Changelog
930
962
963
+ ## 1.12
964
+
965
+ * Update the behavior for variable augmentations.
966
+
931
967
## 1.11
932
968
933
- * Alter and clarify the semantics around augmenting external declarations.
934
- * Allow non-abstract classes to have implictly abstract members which are
935
- implemented in an augmentation.
969
+ * Alter and clarify the semantics around augmenting external declarations.
970
+ * Allow non-abstract classes to have implictly abstract members which are
971
+ implemented in an augmentation.
936
972
937
973
## 1.10
938
974
0 commit comments