11# Augmentation Libraries
22
33Author: rnystrom@google.com , jakemac@google.com
4- Version: 1.11 (see [ Changelog] ( #Changelog ) at end)
4+ Version: 1.12 (see [ Changelog] ( #Changelog ) at end)
55
66Augmentation libraries allow splitting a Dart library into files. Unlike part
77files, 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:
316316 initializer if the member being augmented is not a field with an
317317 initializer.
318318
319- **TODO:** Define the behavior when a field is augmented by a getter or
320- setter, and then later again by a field.
321-
322319* **Augmenting functions**: When augmenting a function, `augment super` refers
323320 to the augmented function. Tear offs are allowed.
324321
@@ -441,12 +438,12 @@ this interact with type checking calls to the function?**
441438
442439### Augmenting variables, getters, and setters
443440
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 .
450447
451448[ uniform ] : https://en.wikipedia.org/wiki/Uniform_access_principle
452449
@@ -489,23 +486,53 @@ More specifically:
489486 non-final variable in the main library. Inside the augmenting setter, an
490487 ` augment super = ` expression invokes the original setter.
491488
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
507530 ` 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.
509536
510537 If the variable declaration in the original library does not have a type
511538 annotation, then the type is inferred only using the original library's
@@ -519,6 +546,11 @@ It is a compile-time error if:
519546
520547* The original and augmenting declarations do not have the same type.
521548
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+
522554* An augmenting initializer uses ` augment super ` and the original declaration
523555 is not a variable with an initializer.
524556
@@ -529,11 +561,11 @@ It is a compile-time error if:
529561* A non-final variable is augmented with a final variable. We don't want to
530562 leave the original setter in a weird state.
531563
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.
537569
538570### Augmenting enum values
539571
@@ -928,11 +960,15 @@ language and our tools.
928960
929961## Changelog
930962
963+ ## 1.12
964+
965+ * Update the behavior for variable augmentations.
966+
931967## 1.11
932968
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.
936972
937973## 1.10
938974
0 commit comments