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

Unquoting computed values in comptime fails in certain positions #5916

Closed
Thunkar opened this issue Sep 4, 2024 · 0 comments · Fixed by #5924
Closed

Unquoting computed values in comptime fails in certain positions #5916

Thunkar opened this issue Sep 4, 2024 · 0 comments · Fixed by #5924
Labels
bug Something isn't working

Comments

@Thunkar
Copy link
Contributor

Thunkar commented Sep 4, 2024

Aim

#[derive_via(derive_serialize)]
trait Serialize<let N: u32> {
    fn serialize(self) -> [Field; N];
}

fn flatten_to_fields(name: Quoted, typ: Type) -> ([Quoted], [Quoted]) {
    // ...not important, aux function that given name/type
    // returns a slice of flattened Fields, for example: self.a, self.b self.nested.a, self.an_array[i] 
    // It also returns aux vars needed to generate said array
    // for example in case strings exist in the struct
    // and we need let field_as_str = str.to_bytes();
    (fields, aux_vars)
}

comptime fn derive_serialize(s: StructDefinition) -> Quoted {
    let typ = s.as_type();
    let (fields, aux_vars) = flatten_to_fields(quote { self }, typ);
    let aux_vars_quote = if aux_vars.len() > 0 {
        let joint = aux_vars.join(quote {;});
        quote { $joint; }
    } else {
        quote {}
    };

    let field_serializations = fields.join(quote {,});
    // Here comes trouble
    let serialized_len = fields.len(); // Setting this to a constant doesn't work either
    quote {
        impl Serialize<$serialized_len> for $typ {
            fn serialize(self) -> [Field; $serialized_len] {
                $aux_vars_quote
                [ $field_serializations ]
            }
        }
    }
}

In the above example, serialized_len cannot be unquoted into the trait impl generic, compiler fails with

error: Failed to parse macro's token stream into an expression
   ┌─ src/main.nr:75:1
   │    
75 │ ╭ ╭ #[derive(Serialize)]
76 │ │ │ struct Smol {
77 │ │ │     a: Field,
78 │ │ │     b: Field,
79 │ │ │ }
   │ ╰─│─'
   │   ╰─' expected <, where or { after impl type
   │    
   = The resulting token stream was: impl Serialize < (UnquoteMarker) > for (type) { fn serialize ( self ) -> [ Field ; (UnquoteMarker) ] { [ self . a as Field , self . b as Field ] } }
   = To avoid this error in the future, try adding input validation to your macro. Erroring out early with an `assert` can be a good way to provide a user-friendly error message

Expected Behavior

Example above should work

Bug

From a slack convo with @jfecher

Ahh, ok. So when we unquote expressions we actually usually keep them as expressions to avoid re-typechecking them and stuff. We leave little “UnquoteMarker” tokens where this happens, and these are later picked up by the parser as expressions. What is happening here is that the parser sees an UnquoteMarker in a type position and says “No, I wanted a Type, not an expression 😤.” Should be a quick fix.

To Reproduce

Workaround

None

Workaround Description

No response

Additional Context

No response

Project Impact

None

Blocker Context

No response

Nargo Version

No response

NoirJS Version

No response

Proving Backend Tooling & Version

No response

Would you like to submit a PR for this Issue?

None

Support Needs

No response

@Thunkar Thunkar added the bug Something isn't working label Sep 4, 2024
@github-project-automation github-project-automation bot moved this to 📋 Backlog in Noir Sep 4, 2024
@Thunkar Thunkar changed the title Unquoting computed values in comptime fails in certain positions) Unquoting computed values in comptime fails in certain positions Sep 4, 2024
github-merge-queue bot pushed a commit that referenced this issue Sep 4, 2024
# Description

## Problem

Resolves #5916

## Summary

## Additional Context

I think there might be other `Value`s that we could convert into tokens,
like `String`, but I didn't want to handle those in this PR (should it
be `Str` or `RawStr`? etc.). And it's possible that we only need this
special logic for integers anyway.

## Documentation

Check one:
- [x] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.

# PR Checklist

- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
@github-project-automation github-project-automation bot moved this from 📋 Backlog to ✅ Done in Noir Sep 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

1 participant