Yes, the functionality you ask is the @after_verify callback in Elixir
v1.14. It is used by LiveView to provide functionality similar to Surface
and also the new Phoenix.VerifiedRoutes. :)

On Fri, Sep 16, 2022 at 14:43 Marlus Saraiva <marlus.sara...@gmail.com>
wrote:

> Hi Zach!
>
> The only way you can minimize the transitive dependency problem is by
> removing the compile-time deps. I struggled with this for years with
> Surface, and as you did, I tried the approach of removing the runtime deps
> to avoid them from turning into transitive compile-time deps. Eventually, I
> realized that avoiding compile-time deps would be the only way to have a
> permanent solution and started removing any implementation that required
> information at compile-time. As soon as LV v0.8 is out, we'll wrap up that
> work, so we don't expect further issues after that. In the meantime, to
> solve the problem, I added a fix that drastically cut down those
> dependencies, which was to convert the `compile` deps into `export` deps,
> by using `import` instead of `require`. For this to work properly, I have
> to generate and automatically rename a signature function to force the
> recompilation of direct callers whenever the component's metadata (props,
> slots, etc) changes. Otherwise, it would only recompile them if you added
> or removed another function.
>
> It seems to me that Elixir could provide a way to hook into the compiler
> allowing DSL developers to inform a criteria that could be used to trigger
> callers' recompilation. Similar to `__mix_recompile__?`. Maybe something
> like `__export_changed__?` or anything else. With this approach, DSL
> authors could replace the `compile` deps with `export` deps as long as the
> changes in that dependency don't need to be propagated to other modules
> other than the callers. This is the case for Surface and many other libs,
> like Commanded, for instance. I'm not sure the proposed solution would
> solve your issue with Ash but I thought it was worth bringing it here since
> it may solve issues on other libs.
>
> José, is something like that feasible?
>
>
>
> On Tuesday, September 13, 2022 at 8:37:24 PM UTC-3 zachary....@gmail.com
> wrote:
>
>> Well, its runtime dependencies that create transitive compile time
>> dependencies, isn't it? So if I have a function like
>>
>> defmodule Foo do
>>   # callers are aware that they can't use the module at compile time
>>   def returns_a_module() do
>>      SomeSpecificModule
>>   end
>>
>>   def something_used_at_compile_time() do
>>     10
>>   end
>> end
>>
>> # and then some other module
>>
>> defmodule Bar do
>>   @something Foo.something_used_at_compile_time()
>> end
>>
>> This induces a transitive compile time dependency from Bar to
>> SomeSpecificModule.
>>
>> In the case of Ash DSLs, for example, this happens because we store the
>> resulting configuration in a module attribute. Users are aware that you
>> can't call these pluggable modules at compile time. Only the framework code
>> calls those modules. The above example is contrived, of course, I'm not
>> suggesting that we need a feature to make *that* work, just trying to draw
>> some kind of parallel.
>>
>> I don't see a reasonable way to handle this without essentially removing
>> the ability to use modules in the way that we are. It would be a pretty
>> unreasonable amount of work/change for users to change the way that we plug
>> behavior in Ash.
>>
>> To me, another kind of module dependency, like `runtime-only`, would
>> solve for this, and it would have to be explicitly requested, i.e
>> `expand_literal(.., runtime_only: true)`. Then when determining transitive
>> compile time dependencies, the compiler would not use those modules.
>>
>>
>> On Tue, Sep 13, 2022 at 6:51 PM, José Valim <jose....@dashbit.co> wrote:
>>
>>> As I mentioned, the issue on transitive compile-time dependencies are
>>> the compile-time deps, not the runtime ones. So I would focus on how to
>>> eliminate those. Otherwise I am not sure we will agree on the problem
>>> statement. :)
>>>
>>> On Wed, Sep 14, 2022 at 12:49 AM Zach Daniel <zachary.s.dan...@gmail.com>
>>> wrote:
>>>
>> Although the solution I originally proposed may not be correct (totally
>>>> fine with me [image: 😃]), I think the problem statement is still
>>>> valid. Can we agree that there are some cases where you may want to
>>>> reference a module without creating transitive compile time dependencies,
>>>> i.e in the case of a DSL like what Ash provides?
>>>>
>>>>
>>>> On Sun, Sep 11, 2022 at 3:08 PM, Zach Daniel <
>>>> zachary.s.dan...@gmail.com> wrote:
>>>>
>>> Hm...yeah, that makes sense. Are there other things a runtime dependency
>>>>> is meant to do aside from ensure that transitive compile time dependencies
>>>>> are properly tracked? If so, is there a way to solve for the transitive
>>>>> dependencies without removing the runtime dependency? Because ultimately
>>>>> the idea here is that this module is essentially just a big
>>>>> validated/extensible configuration. The resource itself doesn't do
>>>>> anything. So requiring things that refer to a resource to recompile when
>>>>> any of the modules it refers to in a `change` like that is unnecessary.
>>>>> However we can express that reality is totally fine with me.
>>>>>
>>>>>
>>>>> On Sunday, September 11, 2022 at 3:05:18 PM UTC-4 José Valim wrote:
>>>>>
>>>>>> The issue is in the transitive compile time dependencies, not the
>>>>>> runtime dependencies.
>>>>>>
>>>>>> I don't think we should be encouraging removing the runtime
>>>>>> dependencies when they are explicitly listed in the code as above. When
>>>>>> done via configuration, at least you are not literally listing it.
>>>>>>
>>>>>> On Sun, Sep 11, 2022 at 8:59 PM Zach Daniel <zachary....@gmail.com>
>>>>>> wrote:
>>>>>>
>>>>>>> So all we we do is hold onto the module, and then at runtime we go
>>>>>>> through the list of modules that we should call and call a specific
>>>>>>> function on them. Requiring a runtime dependency for that is causing 
>>>>>>> really
>>>>>>> slow compile times because of transitive dependencies. Maybe there is 
>>>>>>> some
>>>>>>> consequence I don't see, but I removed the runtime dependencies by
>>>>>>> disabling the lexical tracker when expanding the alias, and its been 
>>>>>>> that
>>>>>>> way for months w/o anyone reporting any issues with that implementation.
>>>>>>> Aside from having to use `warn: false` if they use aliases.
>>>>>>>
>>>>>>> To me, its the same as if they gave us, instead of a module, an
>>>>>>> `atom` that referred to application configuration, i.e the adapter 
>>>>>>> pattern.
>>>>>>> That would work without a runtime dependency, so why couldn't this?
>>>>>>>
>>>>>>>
>>>>>>> On Sun, Sep 11, 2022 at 2:56 PM, José Valim <jose....@dashbit.co>
>>>>>>> wrote:
>>>>>>>
>>>>>> Sorry, correction: If, at any moment, you call any function from that
>>>>>>>> module at runtime, you must not remove the *runtime* time
>>>>>>>> dependency.
>>>>>>>>
>>>>>>>> On Sun, Sep 11, 2022 at 8:55 PM José Valim <jose....@dashbit.co>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>> Why do you want to remove the runtime dependency when, per your
>>>>>>>>> description:
>>>>>>>>>
>>>>>>>>> > In Ash Framework, we have declarative ways to construct
>>>>>>>>> *runtime* behavior using behaviors.
>>>>>>>>>
>>>>>>>>> Emphasis mine. If, at any moment, you call any function from that
>>>>>>>>> module at runtime, you must not remove the compile time dependency.
>>>>>>>>>
>>>>>>>>> On Sun, Sep 11, 2022 at 8:52 PM Zach Daniel <zachary....@gmail.com>
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>> `expand_literal` removes the compile time dependency, but leaves a
>>>>>>>>>> runtime dependency when used inside of a module.
>>>>>>>>>>
>>>>>>>>>> What I'm trying to do is remove both the compile time dependency
>>>>>>>>>> *and* the runtime dependency, without requiring the use of `warn: 
>>>>>>>>>> false` on
>>>>>>>>>> aliases.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Sunday, September 11, 2022 at 2:31:42 PM UTC-4 José Valim
>>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>>> Sorry, I don't understand the proposal. You mentioned
>>>>>>>>>>> expand_literal, which already removes the compile-time dependency 
>>>>>>>>>>> but keeps
>>>>>>>>>>> the remaining functionality such as warnings. Can you please expand?
>>>>>>>>>>>
>>>>>>>>>>> On Sun, Sep 11, 2022 at 7:57 PM Zach Daniel <
>>>>>>>>>>> zachary....@gmail.com> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> For clarity, the dependency I'm talking about there is the
>>>>>>>>>>>> dependency from `MyApp.User` to `MyApp.User.Changes.HashPassword`.
>>>>>>>>>>>> On Sunday, September 11, 2022 at 1:55:51 PM UTC-4 Zach Daniel
>>>>>>>>>>>> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>> In Ash Framework, we have declarative ways to construct
>>>>>>>>>>>>> runtime behavior using behaviors. So an Ash resource might look 
>>>>>>>>>>>>> like this:
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> ```elixir
>>>>>>>>>>>>> defmodule MyApp.User do
>>>>>>>>>>>>>   use Ash.Resource
>>>>>>>>>>>>>
>>>>>>>>>>>>>   alias MyApp.User.Changes.HashPassword
>>>>>>>>>>>>>
>>>>>>>>>>>>>   attributes do
>>>>>>>>>>>>>     uuid_primary_key :id
>>>>>>>>>>>>>    ....
>>>>>>>>>>>>>   end
>>>>>>>>>>>>>
>>>>>>>>>>>>>   actions do
>>>>>>>>>>>>>     create :register do
>>>>>>>>>>>>>       change HashPassword
>>>>>>>>>>>>>     end
>>>>>>>>>>>>>   end
>>>>>>>>>>>>> end
>>>>>>>>>>>>> ```
>>>>>>>>>>>>>
>>>>>>>>>>>>> However, by default, this would incur a compile time
>>>>>>>>>>>>> dependency. This compile time dependency is unnecessary, as we 
>>>>>>>>>>>>> won't call
>>>>>>>>>>>>> any functions on this module or use it in any way until runtime.
>>>>>>>>>>>>>
>>>>>>>>>>>>> That optimization is well and good, but due to transitive
>>>>>>>>>>>>> compile time dependencies, we see some interesting behavior. 
>>>>>>>>>>>>> Something
>>>>>>>>>>>>> you'd often see in a change module is things like pattern 
>>>>>>>>>>>>> matching on other
>>>>>>>>>>>>> resources, or the resource in question in function heads. 
>>>>>>>>>>>>> Resources are
>>>>>>>>>>>>> meant to be introspectable at compile time, and so this runtime 
>>>>>>>>>>>>> dependency
>>>>>>>>>>>>> on a change, with a compile time dependency on a resource, incurs 
>>>>>>>>>>>>> a
>>>>>>>>>>>>> transitive compile time dependency. This problem multiplies over 
>>>>>>>>>>>>> time, and
>>>>>>>>>>>>> causes users to have to do things solely to optimize compile 
>>>>>>>>>>>>> times, like
>>>>>>>>>>>>> only use map pattern matches instead of struct pattern matches.
>>>>>>>>>>>>>
>>>>>>>>>>>>> So what we do is we actually disable the lexical tracker when
>>>>>>>>>>>>> accepting certain parts of the DSL. This prevents *any* 
>>>>>>>>>>>>> dependency.
>>>>>>>>>>>>> Naturally, at compile time you are no longer safe to call a 
>>>>>>>>>>>>> resource's
>>>>>>>>>>>>> change module as changes in that module won't cause recompiles, 
>>>>>>>>>>>>> but that
>>>>>>>>>>>>> was never a thing you should have done in the first place so I'm 
>>>>>>>>>>>>> not
>>>>>>>>>>>>> worried about that.
>>>>>>>>>>>>>
>>>>>>>>>>>>> This leads us to the primary issue: disabling the lexical
>>>>>>>>>>>>> tracker when expanding aliases also causes warnings about unused 
>>>>>>>>>>>>> aliases,
>>>>>>>>>>>>> even though they *are* used. I believe I've brought this issue up 
>>>>>>>>>>>>> before
>>>>>>>>>>>>> and we were hoping that the feature introduced in 1.14 for 
>>>>>>>>>>>>> `defimpl` would
>>>>>>>>>>>>> help, but that only helps prevent compile time issues, which is 
>>>>>>>>>>>>> something I
>>>>>>>>>>>>> had already solved for in the same way it was solved for 1.14. 
>>>>>>>>>>>>> I've laid it
>>>>>>>>>>>>> all out to help clarify exactly *why* I need it so perhaps 
>>>>>>>>>>>>> someone can
>>>>>>>>>>>>> point me in a better direction.
>>>>>>>>>>>>>
>>>>>>>>>>>>> The simplest thing that could help:
>>>>>>>>>>>>>
>>>>>>>>>>>>> A way to tell the lexical tracker that an alias has just been
>>>>>>>>>>>>> referenced without inducing any kind of compile or runtime 
>>>>>>>>>>>>> dependency. The
>>>>>>>>>>>>> idea is to just prevent it from warning about the alias.
>>>>>>>>>>>>>
>>>>>>>>>>>>> I'm open to other solutions as well.
>>>>>>>>>>>>>
>>>>>>>>>>>> --
>>>>>>>>>>>> You received this message because you are subscribed to the
>>>>>>>>>>>> Google Groups "elixir-lang-core" group.
>>>>>>>>>>>> To unsubscribe from this group and stop receiving emails from
>>>>>>>>>>>> it, send an email to elixir-lang-co...@googlegroups.com.
>>>>>>>>>>>> To view this discussion on the web visit
>>>>>>>>>>>> https://groups.google.com/d/msgid/elixir-lang-core/54627973-7b74-47d7-9e35-4270621e6c91n%40googlegroups.com
>>>>>>>>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/54627973-7b74-47d7-9e35-4270621e6c91n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>>>>>>>> .
>>>>>>>>>>>>
>>>>>>>>>>> --
>>>>>>>>>> You received this message because you are subscribed to the
>>>>>>>>>> Google Groups "elixir-lang-core" group.
>>>>>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>>>>>> send an email to elixir-lang-co...@googlegroups.com.
>>>>>>>>>>
>>>>>>>>> To view this discussion on the web visit
>>>>>>>>>> https://groups.google.com/d/msgid/elixir-lang-core/22887a7e-a1b6-4ccc-98bf-69a5ad3551a5n%40googlegroups.com
>>>>>>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/22887a7e-a1b6-4ccc-98bf-69a5ad3551a5n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>>>>>> .
>>>>>>>>>>
>>>>>>>>> --
>>>>>>>> You received this message because you are subscribed to the Google
>>>>>>>> Groups "elixir-lang-core" group.
>>>>>>>>
>>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>>>> send an email to elixir-lang-co...@googlegroups.com.
>>>>>>>>
>>>>>>> To view this discussion on the web visit
>>>>>>>> https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2BVkL%2B1V7LTDVyzhCqcNWrmHFPoWx2Fp916Ur%2ByL%2BiVBA%40mail.gmail.com
>>>>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2BVkL%2B1V7LTDVyzhCqcNWrmHFPoWx2Fp916Ur%2ByL%2BiVBA%40mail.gmail.com?utm_medium=email&utm_source=footer>
>>>>>>>> .
>>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> You received this message because you are subscribed to the Google
>>>>>>> Groups "elixir-lang-core" group.
>>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>>> send an email to elixir-lang-co...@googlegroups.com.
>>>>>>>
>>>>>> To view this discussion on the web visit
>>>>>>> https://groups.google.com/d/msgid/elixir-lang-core/l7xp6eut.444ff913-f528-4b88-805a-cac120cdb4d6%40we.are.superhuman.com
>>>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/l7xp6eut.444ff913-f528-4b88-805a-cac120cdb4d6%40we.are.superhuman.com?utm_medium=email&utm_source=footer>
>>>>>>> .
>>>>>>>
>>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "elixir-lang-core" group.
>>>>>
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an email to elixir-lang-core+unsubscr...@googlegroups.com.
>>>>>
>>>>
>>>>> To view this discussion on the web visit
>>>>> https://groups.google.com/d/msgid/elixir-lang-core/072bb99d-09a0-4567-a934-f8893015dd91n%40googlegroups.com
>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/072bb99d-09a0-4567-a934-f8893015dd91n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>> .
>>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "elixir-lang-core" group.
>>>>
>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to elixir-lang-core+unsubscr...@googlegroups.com.
>>>
>>>
>>>> To view this discussion on the web visit
>>>> https://groups.google.com/d/msgid/elixir-lang-core/l80s9s37.13dfe243-83b3-4133-8aad-7a86910f56fa%40we.are.superhuman.com
>>>> <https://groups.google.com/d/msgid/elixir-lang-core/l80s9s37.13dfe243-83b3-4133-8aad-7a86910f56fa%40we.are.superhuman.com?utm_medium=email&utm_source=footer>
>>>> .
>>>
>>>
>>>> --
>>>
>> You received this message because you are subscribed to the Google Groups
>>> "elixir-lang-core" group.
>>>
>> To unsubscribe from this group and stop receiving emails from it, send an
>>> email to elixir-lang-core+unsubscr...@googlegroups.com.
>>> To view this discussion on the web visit
>>> https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4J8qxM%3DKxMUUW6X%2Bt%2BrD9rKn0yDHbDY1fDgopxRvtNn5A%40mail.gmail.com
>>> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4J8qxM%3DKxMUUW6X%2Bt%2BrD9rKn0yDHbDY1fDgopxRvtNn5A%40mail.gmail.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>>
>> --
> You received this message because you are subscribed to the Google Groups
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to elixir-lang-core+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/elixir-lang-core/325ea272-674a-4a5a-9228-6af11579bd05n%40googlegroups.com
> <https://groups.google.com/d/msgid/elixir-lang-core/325ea272-674a-4a5a-9228-6af11579bd05n%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elixir-lang-core+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4J0Wxqc%3Dq2Cz5JhXEz05hYxG_hWeaOXS0ORdOpyQqxtuQ%40mail.gmail.com.

Reply via email to