@@ -19,8 +19,8 @@ each file is made of separate top-level declarations.
1919
2020However, sometimes a single declaration is too large to fit comfortably
2121in a file. Dart libraries and even part files are no help there. Because of
22- this, users have asked for something like partial classes in C# ([ #252 ] [ ] 71 👍,
23- [ #678 ] [ ] 18 👍). C# also supports splitting [ the declaration and implementation
22+ this, users have asked for something like partial classes in C# ([ #252 ] [ ] 83 👍,
23+ [ #678 ] [ ] 20 👍). C# also supports splitting [ the declaration and implementation
2424of methods into separate files] [ partial ] .
2525
2626[ #252 ] : https://github.com/dart-lang/language/issues/252
@@ -50,11 +50,11 @@ in both directions:
5050 fills in implementation and adds capabilities to it. That's how freezed and
5151 built_value work.
5252
53- * Other times, a code generator produces code with default basic behavior and
54- that a human author then wants to tweak or refine it . You see this sometimes
55- with FFI where you a code generator provides a default API to some external
56- system but where you want to layer on hand-authored code to provide a more
57- natural Dart-like experience.
53+ * Other times, a code generator produces code with default basic behavior that
54+ a human author then wants to tweak or refine. You see this sometimes with
55+ FFI where a code generator provides a default API to some external system
56+ but where you want to layer on hand-authored code to provide a more natural
57+ Dart-like experience.
5858
5959Having a mixture of hand-authored and generated code works well when the
6060generated code consists of completely separate declarations from the
@@ -65,35 +65,22 @@ adding *augmentations*.
6565
6666### Augmentation declarations
6767
68- This feature introduces the modifier ` augment ` as the first token of many
69- kinds of declarations. These declarations are known as * augmentation
70- declarations * .
68+ A declaration marked with the modifier ` augment ` creates an * augmentation
69+ declaration * (or just "augmentation"). In contrast, an unmarked declaration is
70+ an * introductory declaration * .
7171
72- * In Dart without this feature there are no augmentation declarations. Now
73- that we are adding augmentation declarations we need to have a term that
74- denotes a declaration which is not an augmentation. That is, it is one of
75- the "normal" declarations that we've had all the time.*
72+ An augmentation declaration doesn't create a new entity in the program. Instead,
73+ it adds to some existing introductory declaration with the same name.
74+ Augmentation declarations can affect types, functions, members, and almost any
75+ other kind of declaration in Dart. They can add members to classes, append
76+ values to enums, append types to ` with ` or ` implements ` clauses, fill in missing
77+ function bodies, etc.
7678
77- We say that a declaration which is not an augmentation declaration is an
78- * introductory declaration* .
79-
80- Augmentation declarations include:
81-
82- * Type augmentations, which can add new members to types, add new values to
83- enums, or add to the ` with ` or ` implements ` clauses.
84-
85- * Function augmentations, which can provide a body.
86-
87- These operations cannot be expressed today using only imports, exports, or
88- part files. Any Dart file (library file or part file) can contain
89- augmentation declarations. * In particular, an augmentation can augment a
90- declaration in the same file in which it occurs.*
91-
92- An augmentation can fill in a body for a declared member that has no body, but
93- can't * replace* an existing body or add to it. In order to allow augmentations
94- to provide bodies for static methods and top-level functions, we allow
95- declarations of those to be "abstract" and lack a body as long as a body is
96- eventually provided by an augmenting declaration.
79+ An augmentation can be in the same file as the introductory declaration it
80+ applies to, or in separate part files, but they must both be in the same
81+ library. Augmentations allow authoring a library in multiple separate pieces or
82+ files (some of which are likely generated) in a flexible manner, but they can't
83+ inject new behavior into libraries outside of the library author's control.
9784
9885### Design principle
9986
@@ -279,6 +266,9 @@ augmentations are matched with their introductory declaration by name, unnamed
279266extensions can't be augmented. * Doing so wouldn't accomplish anything anyway.
280267Just make two separate unnamed extensions.*
281268
269+ Also note that an augmentation of an extension can't specify an ` on ` clause. It
270+ always uses the same ` on ` clause as the introductory declaration.
271+
282272## Static semantics
283273
284274### Augmentation context
@@ -401,12 +391,12 @@ library.
401391
402392### Type annotation inheritance
403393
404- An augmenting declaration may have no type annotations for a return type,
405- variable type, parameter type, or type parameter bound. In the last case,
406- that includes omitting the ` extends ` keyword. For a variable or parameter,
407- a ` var ` keyword may replace the type .
394+ An augmenting declaration may omit type annotations for a return type, variable
395+ type, parameter type, or type parameter bound. In the last case, that includes
396+ omitting the ` extends ` keyword. For a variable, a ` var ` keyword replaces the
397+ type if the variable isn't ` final ` .
408398
409- If the type annotation or type parameter bound is omitted in the augmenting
399+ If a type annotation or type parameter bound is omitted in the augmenting
410400declaration, it is inferred to be the same as the corresponding type annotation
411401or type parameter bound in the declaration being augmented.
412402
@@ -447,7 +437,8 @@ versioned change, to avoid breaking pre-feature code.
447437* D* augments a declaration * I* with the same name and in the same augmentation
448438context as * D* . There may be multiple augmentations in the augmentation context
449439of * D* . More precisely, * I* is the declaration before * D* and after every other
450- declaration before * D* .
440+ declaration before * D* . * (See "Application order" for the definition of * before*
441+ and * after* .)*
451442
452443It's a ** compile-time error** if there is no matching declaration * I* . * In other
453444words, it's an error to have a declaration marked ` augment ` with no declaration
@@ -464,6 +455,17 @@ ones must be.*
464455An augmentation declaration does not introduce a new name into the surrounding
465456scope. * We could say that it attaches itself to the existing name.*
466457
458+ It's a ** compile-time error** if an augmentation doesn't have the same kind as
459+ the introductory declaration. For example, augmenting a ` class ` with a ` mixin ` ,
460+ an ` enum ` with a function, a method with a getter, etc.
461+
462+ The exception is that a variable declaration (introductory or augmenting) is
463+ treated as a getter declaration (and a setter declaration if non-final) for
464+ purposes of augmentation. These implicit declarations can augment and be
465+ augmented by other explicit getter and setter declarations. * In other words,
466+ variables are never augmented or augmenting, only the getters and possibly
467+ setters that they induce are.*
468+
467469### Complete and incomplete declarations
468470
469471Augmentations aren't allowed to * replace* code, so they mostly add entirely new
@@ -473,22 +475,23 @@ augmentations can fill in a body for an augmented declaration that lacks one.
473475More precisely, a function or constructor declaration (introductory or
474476augmenting) is * incomplete* if all of:
475477
476- * The body syntax is ` ; ` .
478+ * It has no body. * That means no ` { ... } ` or ` => ...; ` but only ` ; ` . *
477479
478480* The function is not marked ` external ` . * An ` external ` function is considered
479481 to have a body, just not one that is visible as Dart code.*
480482
481- * There is no redirection, initializer list, initializing formals, or super
482- parameters. * Obviously, this only applies to constructor declarations.*
483+ * There is no redirection, initializer list, initializing formals, field
484+ parameters, or super parameters. * Obviously, this only applies to
485+ constructor declarations.*
483486
484487If a declaration is not * incomplete* then it is * complete* .
485488
486489It's a ** compile-time error** if an augmentation is complete and any declaration
487490before it in the augmentation chain is also complete. * In other words, once a
488491declaration has acquired a body, no augmentation can replace it with another.*
489492
490- * It is allowed to augment a complete declaration long as the augmentation itself
491- is incomplete. This can be useful for an augmentation to add metadata.*
493+ * It is allowed to augment a complete declaration as long as the augmentation
494+ itself is incomplete. This can be useful for an augmentation to add metadata.*
492495
493496* Examples:*
494497
@@ -616,6 +619,20 @@ augment enum E { v5 }
616619
617620* The resulting enum has values ` v1 ` , ` v2 ` , ` v3 ` , ` v4 ` , and ` v5 ` , in that order.*
618621
622+ * A consequence of application order is that an augmentation in one part file can
623+ augment an introductory declaration in a sibling part file. This may be
624+ confusing since the augmentation affects a declaration that can't be found
625+ anywhere in its ` part of ` chain.*
626+
627+ * However, restricting augmentations to only apply to declarations _ above_ (not
628+ _ before_ ) the augmentation would complicate code generators and potentially
629+ require them to generate one part file per input part file instead of one part
630+ file for the entire library. To avoid that, the rule for where the introductory
631+ declaration can be found is intentionally loose so that a code generator can
632+ produce one part file which is appended to the main library and which is able to
633+ reliably augment any declaration in the entire library regardless of what part
634+ file they are introduced in.*
635+
619636### Augmenting class-like declarations
620637
621638A class, enum, extension, extension type, mixin, or mixin class declaration
@@ -627,13 +644,18 @@ augment class SomeClass {
627644}
628645```
629646
630- Mixin application classes can't be augmented.
647+ Mixin application classes can't be augmented:
631648
632- A class, enum, extension type, mixin, or mixin class augmentation may
633- specify ` extends ` , ` implements ` and ` with ` clauses (when generally
634- supported). The types in these clauses are appended to the introductory
635- declarations' clauses of the same kind, and if that clause did not exist
636- previously, then it is added with the new types.
649+ ``` dart
650+ class C = S with M;
651+ augment class C = S with N; // Error.
652+ ```
653+
654+ A class, enum, extension type, mixin, or mixin class augmentation may specify
655+ ` extends ` , ` implements ` and ` with ` clauses (when otherwise supported). The types
656+ in these clauses are appended to the introductory declarations' clauses of the
657+ same kind, and if that clause did not exist previously, then it is added with
658+ the new types.
637659
638660* Example:*
639661
@@ -650,29 +672,13 @@ including enum values, are added to the instance or static namespace of the
650672corresponding type in the introductory declaration. * In other words, the
651673augmentation can add new members to an existing type.*
652674
653- Instance and static members inside a class-like declaration may themselves
654- be augmentations . In that case, they augment the corresponding members in
655- the same augmentation context, according to the rules in the following
656- subsections.
675+ An instance or static member inside a class-like declaration may itself be an
676+ augmentation . In that case, it augments the corresponding member (the
677+ introducing member with the same name) in the same augmentation context,
678+ according to the rules in the following subsections.
657679
658680It's a ** compile-time** error if:
659681
660- * An augmentation declaration is applied to a declaration of a different kind.
661- For example, augmenting a ` class ` with a ` mixin ` , an ` enum ` with a function,
662- a method with a getter, a constructor with a static method, etc.
663-
664- The exception is that a variable declaration (introductory or augmenting) is
665- treated as a getter declaration (and a setter declaration if non-final) for
666- purposes of augmentation. These implicit declarations can augment and be
667- augmented by other explicit getter and setter declarations. (See "Augmenting
668- variables, getters, and setters" for more details.)
669-
670- * A library contains two top-level declarations with the same name, and one of
671- the declarations is a class-like declaration and the other is not of the
672- same kind, meaning that either one is a class, mixin, enum, extension or
673- extension type declaration, and the other is not the same kind of
674- declaration.
675-
676682* An augmenting class declaration has an ` extends ` clause and any prior
677683 declaration for the same class also has an ` extends ` clause.
678684
@@ -684,12 +690,12 @@ It's a **compile-time** error if:
684690 what is known from reading the introductory declaration will still be true
685691 after augmentation.*
686692
687- * The type parameters of the augmenting declaration do not match the
688- augmented declarations's type parameters. This means there must be
689- the same number of type parameters with the exact same type parameter
690- names (same identifiers) and bounds if any (same * types* , even if they
691- may not be written exactly the same in case one of the declarations
692- needs to refer to a type using an import prefix).
693+ * The type parameters of the augmenting declaration do not match the augmented
694+ declarations's type parameters. This means there must be the same number of
695+ type parameters with the exact same type parameter names (same identifiers)
696+ and bounds if any (same * types* , even if they may not be written exactly the
697+ same in case one of the declarations needs to refer to a type using an
698+ import prefix).
693699
694700 * Since repeating the type parameters is, by definition, redundant, this
695701 restriction doesn't accomplish anything semantically. It ensures that
@@ -698,6 +704,18 @@ It's a **compile-time** error if:
698704 other top-level variables that might be in scope in the library
699705 augmentation.*
700706
707+ The augmenting declaration may choose to omit the bound on any type
708+ parameter, in which case it will be inherited from the augmented
709+ declaration.
710+
711+ ``` dart
712+ foo<X extends num, Y extends X>();
713+ augment foo<X extends num, Y>() { ... }
714+ ```
715+
716+ *Here, `Y` in the augmentation inherits `extends X` from the introductory
717+ declaration.*
718+
701719### Augmenting function and constructor signatures
702720
703721[signature matching]: #augmenting-function-and-constructor-signatures
@@ -712,8 +730,8 @@ signature *matches* if:
712730 (same *types*, even if they may not be written exactly the same in case one
713731 of the declarations needs to refer to a type using an import prefix).
714732
715- * The return type (after type annotation inheritance ) is the same as the
716- augmented declaration's return type.
733+ * The return type (if not omitted ) is the same as the augmented declaration's
734+ return type.
717735
718736* It has the same number of positional and optional parameters as the
719737 augmented declaration.
@@ -722,7 +740,7 @@ signature *matches* if:
722740
723741* For all corresponding pairs of parameters:
724742
725- * They have the same type (after type annotation inheritance ).
743+ * They have the same type (if not omitted in the augmenting declaration ).
726744
727745 * They have the same `required` and `covariant` modifiers.
728746
@@ -749,10 +767,10 @@ signature *matches* if:
749767
750768 ```dart
751769 f1(int _) {}
752- augment f1(int x) {} // OK.
753- augment f1(int _) {} // OK.
754- augment f1(int y) {} // Error, can't change name.
755- augment f1(int _) {} // OK.
770+ augment f1(int x); // OK, first declaration to introduce name .
771+ augment f1(int _); // OK.
772+ augment f1(int y); // Error, can't change name.
773+ augment f1(int _); // OK.
756774 ```
757775
758776 *Note that this is a transitive property.*
@@ -803,12 +821,12 @@ augment class C {
803821}
804822```
805823
806- An optional formal parameter has the default value _ d _ if exactly one
824+ An optional formal parameter has the default value * d * if exactly one
807825declaration of that formal parameter in the augmentation chain specifies a
808- default value, and it is _ d _ . An optional formal parameter does not have an
826+ default value, and it is * d * . An optional formal parameter does not have an
809827explicitly specified default value if none of its declarations in the
810828augmentation chain specifies a default value. The default value is
811- introduced implicitly with the value null in the case where the parameter
829+ introduced implicitly with the value ` null ` in the case where the parameter
812830has a nullable declared type, and no default values for that parameter are
813831specified in the augmentation chain.
814832
@@ -927,6 +945,15 @@ It's a **compile-time error** if:
927945 not a constructor is generative because that affects whether users are
928946 allowed to call the constructor in a subclass's initializer list.*
929947
948+ * A factory constructor is incomplete after all augmentations are applied.
949+
950+ * A constructor whose body is ` ; ` is considered incomplete. This allows an
951+ augmentation to fill in a more interesting body if it wants to. But Dart
952+ also allows a generative constructor to have a body of ` ; ` which is treated
953+ as equivalent to ` {} ` . Thus it is not an error for a _ generative_
954+ constructor to be incomplete after all augmentation are applied. It is
955+ simply treated as having an empty body.*
956+
930957An incomplete constructor can be completed by adding an initializer list and/or
931958a body, or by adding a redirection:
932959
@@ -1189,10 +1216,17 @@ and assume the third point is always true.
11891216
11901217## Changelog
11911218
1219+ ### 1.39
1220+
1221+ * Non-semantic copy editing. Remove some redundant specification. Clarify
1222+ that generative constructors can remain incomplete without error.
1223+
1224+ * Add some rationale for why the introductory declaration only needs to be
1225+ before the augmenting ones and not above (#4377 ).
1226+
11921227### 1.38
11931228
1194- * Generalize the treatment of default values of optional parameters
1195- (addressing issue #4172 ).
1229+ * Generalize the treatment of default values of optional parameters (#4172 ).
11961230
11971231### 1.37
11981232
0 commit comments