noir icon indicating copy to clipboard operation
noir copied to clipboard

Compiler hangs: infinite loop in `Inlining Brillig Calls`

Open aakoshh opened this issue 5 months ago • 1 comments

Aim

Discovered testing https://github.com/noir-lang/noir/pull/8979

The following code causes the compiler to hang:

fn main() {
    unsafe { func_2() };
}

unconstrained fn func_2() {
    loop {
        if false {
            break
        }
    }
}

or like this:

fn main() {
    unsafe { func_2(false) };
}

unconstrained fn func_2(cond: bool) {
    loop {
        if cond {
            break
        }
    }
}

Expected Behavior

Expected it to compile, despite the infinite loop.

Bug

$ cargo run -q -p nargo_cli -- compile --show-ssa
After Verifying no dynamic array indices to reference value elements (1) (step 41):
acir(inline) predicate_pure fn main f0 {
  b0():
    call f1(u1 0)
    return
}
brillig(inline) predicate_pure fn func_2 f1 {
  b0(v0: u1):
    jmp b1()
  b1():
    jmpif v0 then: b2, else: b3
  b2():
    return
  b3():
    jmp b1()
}

^C⏎                                                                                                                                                                                                                                                  

That is the last step of the primary pipeline. If we change the program to remove the infinite loop, we can see that the next step would be After Inlining Brillig Calls (1) (step 42):, which involves running the Brillig VM with constant inputs. In this case it means the compiler never returns, because it gets stuck in the infinite loop.

Maybe there could be some limit to how far we try to evaluate such calls at compile time.

To Reproduce

See above.

Workaround

None

Workaround Description

Not having any constant arguments that cause infinite loops in Brillig functions.

Additional Context

No response

Project Impact

None

Blocker Context

No response

Nargo Version

nargo version = 1.0.0-beta.7 noirc version = 1.0.0-beta.7+45246337701fe88d7f97416ee0715d23acf50ab2 (git version hash: d7030e8c4e05dcba0eb30adac7f0f18458b306f0, is dirty: true)

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

aakoshh avatar Jun 24 '25 10:06 aakoshh

related: https://github.com/noir-lang/noir/issues/5026

Yeah, I'd say that we should add an execute N opcodes method to the brillig vm and then during compilation we can execute some (large) number of opcodes and otherwise just leave the call in place.

TomAFrench avatar Jun 24 '25 10:06 TomAFrench