noir-lang / noir

Noir is a domain specific language for zero knowledge proofs
https://noir-lang.org
Apache License 2.0
897 stars 200 forks source link

fix: Unify macro result type with actual type #6086

Closed jfecher closed 2 months ago

jfecher commented 2 months ago

Description

Problem*

Resolves an issue from @asterite on slack

Summary*

When we type check a macro call we don't know the actual type so we return a fresh type variable.

When we later execute this code at comptime we do know the type, so we should unify the type variable then, potentially catching any inconsistencies. This also makes the value of the type variable known (during evaluation, not type checking!) as in the new test case.

Additional Context

Also fixed an issue where you couldn't call a method as a macro directly and needed an extra unquote! call.

Documentation*

Check one:

PR Checklist*

github-actions[bot] commented 2 months ago

Changes to Brillig bytecode sizes

Generated at commit: f6127e860d7364ca7ccb2dec3197d2394975f897, compared to commit: 78262c96d5b116c77e50653f9059da60824db812

There are no changes in circuit sizes

asterite commented 2 months ago

@jfecher I found that this doesn't work if this happens in a loop:

#[annotation]
mod moo {
    fn foo() {}
    fn barbaz() {}
}

comptime fn annotation(m: Module) {
    for function in m.functions() {
        let name = function.name();
        let name = f"{name}".as_ctstring();
        let string = name.as_quoted_str!();
        let half = half(string);
        println(half);
    }
}

comptime fn half<let N: u32>(s: str<N>) -> u32 {
    N / 2
}

fn main() {}

The error:

error: Expected type str<3>, found type str<6>
   ┌─ src/main.nr:17:18
   │
17 │     let string = name.as_quoted_str!();
   │                  ---------------------

I guess it's because N is bound once and then it can't change.

I tried extracting some of that code to a helper function (a fn(FunctionDefinition) -> u32) but it leads to the same compiler error.

I wonder how we can solve this... 🤔

jfecher commented 2 months ago

That's a hard one since we only do type checking once and not on each loop iteration