Skip to content
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

Add run_before and run_after helpers for attribute ordering #6344

Open
Tracked by #6729
jfecher opened this issue Oct 24, 2024 · 0 comments
Open
Tracked by #6729

Add run_before and run_after helpers for attribute ordering #6344

jfecher opened this issue Oct 24, 2024 · 0 comments
Labels
enhancement New feature or request
Milestone

Comments

@jfecher
Copy link
Contributor

jfecher commented Oct 24, 2024

Problem

After #6326, all attributes are run in the order they're specified in source code by users. However, library authors may have intended orderings for their attributes that users may get wrong. Currently, providing a good error message for this means doing something like the following for every ordering constraint:

comptime mut global must_run_first_run_on: UHashMap<FunctionDefinition, (), BuildHasherDefault<Poseidon2Hasher>>
    = UHashMap::default();

comptime fn must_run_first(f: FunctionDefinition) {
    must_run_first_run_on.insert(f, ());
}

comptime fn must_run_second(f: FunctionDefinition) {
    let order_valid = must_run_first_run_on.contains(f);
    assert(order_valid, "must_run_second should always run after must_run_first!");
}

#[must_run_second] // error! must_run_second should always run after must_run_first!
#[must_run_first]
fn foo() {}

Which in the presence of many ordering constraints is very tedious.

Happy Case

We add std::meta::run_before and std::meta::run_after helpers to issue these errors automatically if the ordering constraints are ever invalidated. These would never control the attribute ordering, they'd only issue errors if it is invalidated. Because these are normal functions placed within a function body, users could also have complex ordering constraints e.g. if foo_has_field_bar { must_run_after(fixup_bar) }.

One possible signature for these functions could be:

#[builtin(error_if_run_before)]
comptime fn error_if_run_before<T, Msg>(attr: T, message: Msg) {}

#[builtin(error_if_run_after)]
comptime fn error_if_run_after<T, Msg>(attr: T, message: Msg) {}

One difficulty is how to track more fine grained ordering relationships like that of derive_via and derive where derive_via should run before derive, but only for the same trait. If derive_via is called on a new trait Foo, a derive(Eq) should not error if run previously to that derive_via.

A possible way to solve this is to pass additional data to the attr parameter of the functions above, and have run_after error if run_before was not previously called with the same arguments (determined by equality on T):

comptime fn derive_via(t: TraitDefinition, f: FunctionDefinition) {
    run_before((derive, t), f"derive_via called after derive has already been called for trait {t}");
    ...
}

comptime fn derive(s: StructDefinition, traits: [TraitDefinition]) -> Quoted {
    for t in traits {
        run_after((derive_via, t), f"No trait deriver registered for {t}");
        ...
    }
    ...
}

A disadvantage of this is that it requires both run_before and run_after to be used, so users can't add constraints between an attribute they control and an attribute originating from an external library.

Workaround

None

Workaround Description

No response

Additional Context

No response

Project Impact

None

Blocker Context

No response

Would you like to submit a PR for this Issue?

None

Support Needs

No response

@jfecher jfecher added the enhancement New feature or request label Oct 24, 2024
@github-project-automation github-project-automation bot moved this to 📋 Backlog in Noir Oct 24, 2024
@Savio-Sou Savio-Sou added this to the 1.0 milestone Dec 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: 📋 Backlog
Development

No branches or pull requests

2 participants