Skip to content

Commit 34f4818

Browse files
authored
Update macro spec to allow more introspection in Phase 2. (#3480)
* Update macro spec to allow more introspection in Phase 2. * Address review comments.
1 parent 64de872 commit 34f4818

File tree

1 file changed

+26
-40
lines changed

1 file changed

+26
-40
lines changed

working/macros/feature-specification.md

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -268,36 +268,14 @@ order of macros:
268268
269269
Here, the macros applied to C are run `First()`, `Second()`, then `Third()`.
270270
271-
* **Macros are applied to superclasses, mixins, and interfaces first, in**
272-
**Phase 2** For example:
271+
Aside from these rules, macros are constrained so that the result is the same
272+
whatever the application order. In most cases this achieved by the split into
273+
phases: within each phase macros can run in any order because the output is not
274+
visible to other macros until the next phase. As a special case, introspection
275+
of types in Phase 2 waits as needed for other macro applications to complete,
276+
failing if there is a cycle.
273277
274-
```dart
275-
@Third()
276-
class B extends A with C implements D {}
277-
278-
@Second()
279-
class A implements C {}
280-
281-
@First()
282-
class C {}
283-
284-
@first
285-
class D {}
286-
```
287-
288-
Here, the macros on `A`, `C` and `D` run before the macros on `B`, and `C`
289-
also runs before `A`. But otherwise the ordering is not defined (it is not
290-
observable).
291-
292-
This only applies to Phase 2, because it is the only phase where the order
293-
would be observable. In particular this allows macros running on `B` to see
294-
any members added to its super classes, mixins, or interfaces, by other
295-
macros running in phase 2.
296-
297-
Aside from these rules, macro introspection is limited so that evaluation order
298-
is not user visible. For example, if two macros are applied to two methods in
299-
the same class, there is no way for those macros to interfere with each other
300-
such that the application order can be detected.
278+
TODO: give an example of a cycle.
301279
302280
### Augmentation library structure and ordering
303281
@@ -606,17 +584,21 @@ of a function or initializer for a variable. It is encouraged to provide a body
606584
(or initializer) if possible, but you can opt to wait until the definition phase
607585
if needed.
608586

609-
When applied to a class, enum, or mixin a macro in this phase can introspect on
610-
all of the members of that class and its superclasses, but it cannot introspect
611-
on the members of other types. For mixins, the `on` type is considered a
612-
superclass and is introspectable. Note that generic type arguments are not
613-
introspectable.
587+
Phase two macros can introspect on all of the members of a type. If the type
588+
to be introspected is declared in the same library cycle and has one or more
589+
macros applied to it then this introduces an ordering constraint between the
590+
macro applications: the introspection call waits for complete results before
591+
returning, meaning it waits for the macro applications on the target type to
592+
finish.
614593

615-
When applied to an extension, a macro in this phase can introspect on all of the
616-
members of the `on` type, as well as its generic type arguments and the bounds
617-
of any generic type parameters for the extension.
594+
If a cycle arises in macro applications waiting for other macro applications to
595+
complete then a `StateError ` is thrown.
618596

619-
TODO: Define the introspection rules for extension types.
597+
Rules might be added in future to decide in some specific cases which macro
598+
should run with incomplete introspection results to break a cycle. For example,
599+
there might be a rule specifying that an application to a superclass runs first
600+
with incomplete results, allowing an application to a subclass to run
601+
afterwards with introspection onto the declarations added.
620602

621603
### Phase 3: Definitions
622604

@@ -629,8 +611,8 @@ function body.
629611
Phase three macros can add new supporting declarations to the surrounding scope,
630612
but these are private to the macro generated code, and never show up in
631613
introspection APIs. These macros can fully introspect on any type reachable from
632-
the declarations they are applied to, including introspecting on members of
633-
classes, etc.
614+
the declarations they are applied to without introducing application ordering
615+
constraints as in Phase 2.
634616

635617
## Macro declarations
636618

@@ -696,6 +678,8 @@ For example, in `ClassDeclarationsMacro`, the introspection object is a
696678
to the immediate superclass, as well as any immediate mixins or interfaces,
697679
but _not_ its members or entire class hierarchy.
698680

681+
TODO: update this example.
682+
699683
### Builder argument
700684

701685
The second argument is an instance of a [builder][] class. It exposes both
@@ -707,6 +691,8 @@ primary method is `declareInClass`, which the macro can call to add a new member
707691
to the class. It also implements the `ClassIntrospector` interface, which allows
708692
you to get the members of the class, as well as its entire class hierarchy.
709693

694+
TODO: update this example.
695+
710696
[builder]: https://github.com/dart-lang/sdk/blob/main/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
711697

712698
### Introspection API ordering

0 commit comments

Comments
 (0)