-
Notifications
You must be signed in to change notification settings - Fork 76
Description
Motivation
Currently the macros depend on the line order of the code. Since recently the way the current macros work break rust analyzer. This was noted in #327.
A solution to this problem is to switch to the Outer Macro pattern, which allows to track the state of the macro without depending on the line order of the code.
Design Detail
The main idea is to use a #[php_module]
macro on a module that contains all the functions, classes, etc. that should be exported to PHP.
As everything in that module is the input to the macro, the macro can track the state of the module and generate the necessary code.
While parsing the 'pseudo' inner macros are evaluated similar to the current macros.
This would look something like this:
#[php_module]
pub mod module {
#[php_function]
fn func() { ... }
#[php_class]
pub struct Example {
[...]
}
#[php_impl]
impl Example {
[...]
}
}
Drawbacks
The main drawback is that all functions, classes, etc. must be defined in the same module. This can make the code harder to read and maintain.
A workaround for this would be to include a require!
macro that allows to include the code from another module. Functionality for this can be added using macro_magic.
It should be noted, that macro_magic
has this warning about that approach:
Any types you may have brought into scope with use statements in the foreign module may or may not be available in their new context without additional use statements.
Another drawback is that this will break existing code that uses the old macro pattern.
Rationale and Alternatives
The main alternative is to drop the #[php_module]
macro and require the user to register all functions, classes, etc. manually (#329).
This gives the author more control over how the module is wired in the end. I guess this would be similar to how crates like actix_web
do things.
While this would work, it would also be a breaking change and not that easy to migrate to as this approach requires some manual work by the author.
Using the Outer Macro pattern would in theory allow to support both patterns, but would make most cases easier.
Another alternative is to keep the current macro pattern and fix the issues with it. This would still depend on the line order of the code and has no guarantee that it will not break again in the future.
Prior Art
This youtube video explains the concept of Outer Macros.