-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use-case: statically extract the dependencies of a function #37
Comments
I think this is a duplicate of #6 - basically some way to view the method body and extract some info from that? |
Possibly. This was meant more as a "here's a problem" without knowing what the solution would be. Feel free to close this if you want |
One complication with looking into function bodies is that this affects how the analyzer decides which changes affect a library API. Normally bodies of top-level functions never affect the API, which means that you can change them and reuse the summary of the library, it still have exactly the same classes, variables, and type. So, you only have to re-resolve this library (could be just the changes function body), but not any other libraries that use the changes library. So far, while prototyping macros in the analyzer, I considered any macro-generated elements as looking only on the API portion of a file, and generating only the APIs (specifically only new class members for now), and we cache the results of macro generators into summaries. It is not out of question to look into function bodies, we just have to be cognizant of the caching considerations. |
Yes the caching implications definitely matter. So far we have only been considering allowing a macro to look at the AST of the thing it directly annotates. So you would not be able to look at function bodies arbitrarily in the program. In theory that would help with invalidation - implementations could treat macro annotated declarations specially and invalidate the macro generation (and summary) whenever their body changes. Likely these macros would be implementing some specific interface as well so you would know which ones actually reach into function bodies and need to be specialized. But yes in general this is one of several concerns with allowing macros to introspect on function bodies 👍 |
Would it not be possible to track what the macro is depending on? There are a few helpful patterns for this, and it would be a caching mechanism independent from what the macro is reading. |
As it is implemented in the analyzer right now, we compute "API signature" of a file based on its parsed AST, without any resolution. So, we don't know whether there are any macro annotations, where they resolved, which interfaces they implement. Then this API signature is combined with other data, and eventually turned into the cache key. If we can find the result by this key, we use it, otherwise we recompute. One of the arcs of work that I started exploring, and was going to continue, until the macro feature became more important, was to implement fine grained dependency tracking, where we actually see which symbols are used by other symbols, and invalidate only affected portions. Then we don't use the cache key, or at least this key does not depend on the API signature, instead we get a cached result and check that it (or its parts) is still valid. With this approach we probably could be able to see that an element was macro-generated, and looked into one or another function body. |
@rrousselGit – in your example Wondering if this info could be hoisted into annotations, etc |
They could be any variable definition, including instance fields. In particular, the use-cases I need to support are: final family = Provider.family<State, Param>(...);
final dependency = Provider<Person>(...);
final provider = Provider((ref) {
Person p = ref.watch(dependency);
String name = ref.watch(dependency.select((p) => p.name));
Param param = <...>
State s = ref.watch(family(param));
String str = ref.watch(family(param).select((s) => s.str);
}); where all Getters/function calls aren't supported (besides Provider getProvider() => ...
final provider = Provider((ref) {
ref.watch(getProvider())
} is invalid If necessary, in the examples from this comment, |
Currently, both Riverpod and flutter_hooks sometimes relies on users having to define a list of dependencies used by a function
An example would be:
or:
The problem with this syntax is, it is error prone.
The interesting thing is, in both examples, this list of dependency is known at compile time.
This means that this secondary parameter could instead be generated by a macro directly with a 100% accuracy.
In particular, I was thinking of changing the first example to be:
which would generate:
Sadly it seems like the current macro API does not give us enough informations about the function content to do such a thing.
The text was updated successfully, but these errors were encountered: