noir-lang/noir

Self referential struct crashes nargo process

Closed this issue · 4 comments

Aim

To create a self referential struct in a slice member

struct SelfReferential
{
    prop : [SelfReferential]
}

and use it in a test

#[test]
unconstrained
fn test_self_referential()
{
    let self_ref = SelfReferential { prop : [] };
}

Expected Behavior

Should work as intended.

Bug

Nargo process crashes during test execution

Testing test_self_referential... 
thread 'main' has overflowed its stack
fatal runtime error: stack overflow

To Reproduce

  1. Create file with code above
  2. Run nargo test

Installation Method

Binary

Nargo Version

0.19.2+d7f919dcc001080ed24616ebbc37426ef7ac7638

Additional Context

No response

Would you like to submit a PR for this Issue?

No

Support Needs

No response

Backtrace:

[hello] Running 1 test functions
[hello] Testing test_self_referential... Stack Overflow:
   0: backtrace_on_stack_overflow::handle_sigsegv
             at /home/work/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-on-stack-overflow-0.3.0/src/lib.rs:94:40
   1: wasmer_vm::trap::traphandlers::trap_handler
             at /home/work/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasmer-vm-4.2.3/src/trap/traphandlers.rs:288:17
   2: <unknown>
   3: alloc::vec::Vec<T,A>::len
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/vec/mod.rs:2050:9
      noirc_frontend::hir_def::types::StructType::get_fields
             at noir/compiler/noirc_frontend/src/hir_def/types.rs:234:20
   4: noirc_frontend::monomorphization::Monomorphizer::convert_type
             at noir/compiler/noirc_frontend/src/monomorphization/mod.rs:748:30
   5: noirc_frontend::monomorphization::Monomorphizer::convert_type
             at noir/compiler/noirc_frontend/src/monomorphization/mod.rs:696:40
   6: noirc_frontend::monomorphization::Monomorphizer::convert_type::{{closure}}
             at noir/compiler/noirc_frontend/src/monomorphization/mod.rs:749:58
      core::iter::adapters::map::map_fold::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/iter/adapters/map.rs:84:28
      core::iter::traits::iterator::Iterator::fold
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/iter/traits/iterator.rs:2481:21
      <core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::fold
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/iter/adapters/map.rs:124:9
   7: core::iter::traits::iterator::Iterator::for_each
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/iter/traits/iterator.rs:856:9
      alloc::vec::Vec<T,A>::extend_trusted
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/vec/mod.rs:2843:17
      <alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/vec/spec_extend.rs:26:9
      <alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/vec/spec_from_iter_nested.rs:62:9
   8: alloc::vec::in_place_collect::<impl alloc::vec::spec_from_iter::SpecFromIter<T,I> for alloc::vec::Vec<T>>::from_iter
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/vec/in_place_collect.rs:167:20
      <alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/alloc/src/vec/mod.rs:2711:9
      core::iter::traits::iterator::Iterator::collect
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/iter/traits/iterator.rs:1895:9
      iter_extended::vecmap
             at noir/compiler/utils/iter-extended/src/lib.rs:14:5
      noirc_frontend::monomorphization::Monomorphizer::convert_type
             at noir/compiler/noirc_frontend/src/monomorphization/mod.rs:749:30
   9: noirc_frontend::monomorphization::Monomorphizer::convert_type
             at noir/compiler/noirc_frontend/src/monomorphization/mod.rs:696:40
  10: noirc_frontend::monomorphization::Monomorphizer::convert_type::{{closure}}
             at noir/compiler/noirc_frontend/src/monomorphization/mod.rs:749:58
      core::iter::adapters::map::map_fold::{{closure}}
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/iter/adapters/map.rs:84:28
      core::iter::traits::iterator::Iterator::fold
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/iter/traits/iterator.rs:2481:21
      <core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::fold
             at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/iter/adapters/map.rs:124:9

We'll need a test in the frontend to prevent constructing recursive types. This can be done when defining a new struct type.

Current approach:

The given test case is currently failing with:

error: Nested slices are not supported
  ┌─ /Users/michaelklein/Coding/rust/noir/test_programs/compile_failure/self_referential_struct/src/main.nr:1:1
  │  
1 │ ╭ struct SelfReferential
2 │ │ {
3 │ │     prop : [SelfReferential]
4 │ │ }
  │ ╰─' Try to use a constant sized array instead

Using the following results in a stack overflow:

struct SelfReferential
{
    prop : Option<SelfReferential>
}

#[test]
unconstrained
fn test_self_referential()
{
    let self_ref = SelfReferential { prop : Option::none() };
}