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

feat: Support printing more types #4071

Merged
merged 10 commits into from
Jan 18, 2024

Conversation

ggiraldez
Copy link
Contributor

@ggiraldez ggiraldez commented Jan 17, 2024

Description

Problem*

As part of our debugger implementation (see #3015) we need to extend the supported types that can be printed. We are using noirc_printable_type to keep values of variables at runtime for debug inspection.

Also resolves #4073

Summary*

This PR adds support for converting these new types:

  • Tuples
  • Slices: lift the restriction to print them and handle arrays with dynamic size (flagging them with a None length in the type)
  • Functions: printed as an opaque <<function>> tag for now
  • Mutable references: printed as an opaque <<mutable ref>> tag for now
  • Unit: this is actually required to fully support function type conversion, for non-closured function references (ie. the environment is () in that case)

The PR also fixes a preexisting bug when printing multiple values using formatted strings with the first ones being structs. Since structs are expanded into tuples which take up more than one field, the printing code would fail to skip over all the fields of the struct.

Additional Context

I've been using this program to test this functionality. If it makes sense, I can add it as an integration test to test_programs/execution_success.

The program produces this output:

(0x01, 0x02, 0x03)
0xbbbb # a = (0x01, 0x02, 0x03) # 0xeeee
(0x01, 0x02, 0x03) == (0x01, 0x02, 0x03)

((0x01, 0x02, 0x03), 0x04, 0x05, 0x06)
0xbbbb # b = ((0x01, 0x02, 0x03), 0x04, 0x05, 0x06) # 0xeeee
((0x01, 0x02, 0x03), 0x04, 0x05, 0x06) == ((0x01, 0x02, 0x03), 0x04, 0x05, 0x06)

<<mutable ref>>
0xbbbb # c = <<mutable ref>> # 0xeeee

<<function>>
0xbbbb # d = <<function>> # 0xeeee

<<function>>
0xbbbb # f = <<function>> # 0xeeee

[0x01, 0x02, 0x03]
0xbbbb # g = [0x01, 0x02, 0x03] # 0xeeee
[0x01, 0x02, 0x03] == [0x01, 0x02, 0x03]

Foo { x: 555, y: 666 } == Foo { x: 555, y: 666 }

Vec { slice: [0x01, 0x02] }
0xbbbb # h = Vec { slice: [0x01, 0x02] } # 0xeeee

[0x01, 0x02]
0xbbbb # j = [0x01, 0x02] # 0xeeee
[0x01, 0x02] == [0x01, 0x02]

[printable_types] Circuit witness successfully solved

Documentation*

Check one:

  • No documentation needed.
  • Documentation included in this PR.
  • [Exceptional Case] Documentation to be submitted in a separate PR.

PR Checklist*

  • I have tested the changes locally.
  • I have formatted the changes with Prettier and/or cargo fmt on default settings.

@vezenovm
Copy link
Contributor

vezenovm commented Jan 17, 2024

Thanks for the PR I was actually just adding Tuple types for printing and you beat me to it :).

Could you add that test under test_programs/execution_success. We also have a debug_logs test where you can add those cases.

@vezenovm
Copy link
Contributor

The PR also fixes a preexisting bug when printing multiple values using formatted strings with the first ones being structs. Since structs are expanded into tuples which take up more than one field, the printing code would fail to skip over all the fields of the struct.

Is there an issue for this bug? Or did you find it on your own?

@ggiraldez
Copy link
Contributor Author

Thanks for the PR I was actually just adding Tuple types for printing and you beat me to it :).

Could you add that test under test_programs/execution_success. We also have a debug_logs test where you can add those cases.

Oh, right! I'll try adding the new cases to debug_logs. Thanks!

@ggiraldez
Copy link
Contributor Author

The PR also fixes a preexisting bug when printing multiple values using formatted strings with the first ones being structs. Since structs are expanded into tuples which take up more than one field, the printing code would fail to skip over all the fields of the struct.

Is there an issue for this bug? Or did you find it on your own?

I just found it while inspecting the printing code. I don't think there's an issue for it. I can create it, no problem.

@vezenovm
Copy link
Contributor

What happens in the case where a type doesn't work w/ ACIR output such as slices or Vectors? Does it just panic?

@vezenovm
Copy link
Contributor

Oh, right! I'll try adding the new cases to debug_logs. Thanks!

It would be great if you could post the output here as well.

@ggiraldez
Copy link
Contributor Author

What happens in the case where a type doesn't work w/ ACIR output such as slices or Vectors? Does it just panic?

It doesn't compile. Seems related to the restriction on slices for Brillig entry points:

The application panicked (crashed).
Message:  not implemented: Unsupported slices as parameter
Location: compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs:67

@vezenovm
Copy link
Contributor

It doesn't compile. Seems related to the restriction on slices for Brillig entry points:

Ah yeah this is currently unsupported as we need to know the exact number of parameters we are passing to a Brillig entry point. We could add support for slices as parameters to Brillig entry points but this is a larger change. Tbh right now I lean towards not supporting slices in the debugger if this is necessary for your work.

Being able to print in Brillig then getting a panic of "Unsupported slices as parameter" when printing in ACIR is going to be confusing to users.

@ggiraldez
Copy link
Contributor Author

It doesn't compile. Seems related to the restriction on slices for Brillig entry points:

Ah yeah this is currently unsupported as we need to know the exact number of parameters we are passing to a Brillig entry point. We could add support for slices as parameters to Brillig entry points but this is a larger change. Tbh right now I lean towards not supporting slices in the debugger if this is necessary for your work.

Being able to print in Brillig then getting a panic of "Unsupported slices as parameter" when printing in ACIR is going to be confusing to users.

I understand. We will have a similar problem with mutable references though. In that case the compiler fails with:

The application panicked (crashed).
Message:  internal error: entered unreachable code: Expected all allocate instructions to be removed before acir_gen
Location: compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs:579

@vezenovm
Copy link
Contributor

vezenovm commented Jan 17, 2024

I understand. We will have a similar problem with mutable references though. In that case the compiler fails with:

Hmm I see. Then we should add a type check of some sort that will return an error if we are attempting to call println w/ mutable references or slices from ACIR.

We probably could do this check during SSA gen as a FunctionContext will store the runtime type of the function for which we are generating SSA.

@ggiraldez
Copy link
Contributor Author

ggiraldez commented Jan 17, 2024

I understand. We will have a similar problem with mutable references though. In that case the compiler fails with:

Hmm I see. Then we should add a type check of some sort that will return an error if we are attempting to call println w/ mutable references or slices from ACIR.

We probably could do this check during SSA gen as a FunctionContext will store the runtime type of the function for which we are generating SSA.

If we want to limit the types for printing, then append_printable_type_info_inner looks like the best place to put the checks. This will affect both Brillig and ACIR output modes, and should remove the source of confusion.

AFAIK that code is only used when handling print/println from the stdlib. This would still allow the debugger instrumentation code to pass slices and mutable references to the oracle functions. And since we're (at least initially) planning to inject the instrumentation code only when compiling in Brillig mode, the debugger would still work for most cases.

As requested above, I filed the bug re: passing structs and multiple arguments and added the new printable types to the debug_logs sample. I put the problematic cases in a separate function, so we can disable/remove them easily if necessary.

@vezenovm
Copy link
Contributor

If we want to limit the types for printing, then append_printable_type_info_inner looks like the best place to put the checks. This will affect both Brillig and ACIR output modes, and should remove the source of confusion.

AFAIK that code is only used when handling print/println from the stdlib. This would still allow the debugger instrumentation code to pass slices and mutable references to the oracle functions. And since we're (at least initially) planning to inject the instrumentation code only when compiling in Brillig mode, the debugger would still work for most cases.

As requested above, I filed the bug re: passing structs and multiple arguments and added the new printable types to the debug_logs sample. I put the problematic cases in a separate function, so we can disable/remove them easily if necessary.

Yeah currently that code is only used when handling print/println from the stdlib. I'm working on enabling assert messages to be able to print more than just strings literals so this will most likely change in the future, but continue as you have been as that work is still in flux. If you are able to add the checks and still allow the debugger instrumentation code then I am good with that. I just don't want users to see Unsupported slices as parameter rather than something like Slices are unsupported to be printed from constrained code.

Will give the code another look!

…e refs

Even though the printing support is there, neither of them can be passed from
ACIR into Brillig. So the restriction is for consistency and to be able to
provide a better error message to users.
Copy link
Contributor

@vezenovm vezenovm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for simplifying the fmtstr execution with that bug fix as well.

@vezenovm vezenovm added this pull request to the merge queue Jan 18, 2024
Merged via the queue into noir-lang:master with commit f5c4632 Jan 18, 2024
29 of 30 checks passed
github-merge-queue bot pushed a commit that referenced this pull request Jan 22, 2024
🤖 I have created a release *beep* *boop*
---


<details><summary>0.23.0</summary>

## [0.23.0](v0.22.0...v0.23.0)
(2024-01-22)


### ⚠ BREAKING CHANGES

* Ban nested slices
([#4018](#4018))
* Breaking changes from aztec-packages
([#3955](#3955))
* Rename Arithmetic opcode to AssertZero
([#3840](#3840))
* remove circuit methods from noir_wasm
([#3869](#3869))

### Features

* Add `assert_max_bit_size` method to `Field`
([#4016](#4016))
([bc9a44f](bc9a44f))
* Add `noir-compiler` checks to `aztec_macros`
([#4031](#4031))
([420a5c7](420a5c7))
* Add a `--force` flag to force a full recompile
([#4054](#4054))
([27a8e68](27a8e68))
* Add dependency resolver for `noir_wasm` and implement `FileManager`
for consistency with native interface
([#3891](#3891))
([c29c7d7](c29c7d7))
* Add foreign call support to `noir_codegen` functions
([#3933](#3933))
([e5e52a8](e5e52a8))
* Add MVP `nargo export` command
([#3870](#3870))
([fbb51ed](fbb51ed))
* Add support for codegenning multiple functions which use the same
structs in their interface
([#3868](#3868))
([1dcfcc5](1dcfcc5))
* Added efficient field comparisons for bn254
([#4042](#4042))
([1f9cad0](1f9cad0))
* Assert maximum bit size when creating a U128 from an integer
([#4024](#4024))
([8f9c7e4](8f9c7e4))
* Avoid unnecessary range checks by inspecting instructions for casts
([#4039](#4039))
([378c18e](378c18e))
* Breaking changes from aztec-packages
([#3955](#3955))
([5be049e](5be049e))
* Bubble up `Instruction::Constrain`s to be applied as early as
possible. ([#4065](#4065))
([66f5cdd](66f5cdd))
* Cached LSP parsing
([#4083](#4083))
([b4f724e](b4f724e))
* Comparison for signed integers
([#3873](#3873))
([bcbd49b](bcbd49b))
* Decompose `Instruction::Cast` to have an explicit truncation
instruction ([#3946](#3946))
([35f18ef](35f18ef))
* Decompose `Instruction::Constrain` into multiple more basic
constraints ([#3892](#3892))
([51cf9d3](51cf9d3))
* Docker testing flow
([#3895](#3895))
([179c90d](179c90d))
* Extract parsing to its own pass and do it in parallel
([#4063](#4063))
([569cbbc](569cbbc))
* Implement `Eq` trait on curve points
([#3944](#3944))
([abf751a](abf751a))
* Implement DAP protocol in Nargo
([#3627](#3627))
([13834d4](13834d4))
* Implement generic traits
([#4000](#4000))
([916fd15](916fd15))
* Implement Operator Overloading
([#3931](#3931))
([4b16090](4b16090))
* **lsp:** Cache definitions for goto requests
([#3930](#3930))
([4a2140f](4a2140f))
* **lsp:** Goto global
([#4043](#4043))
([15237b3](15237b3))
* **lsp:** Goto struct member inside Impl method
([#3918](#3918))
([99c2c5a](99c2c5a))
* **lsp:** Goto trait from trait impl
([#3956](#3956))
([eb566e2](eb566e2))
* **lsp:** Goto trait method declaration
([#3991](#3991))
([eb79166](eb79166))
* **lsp:** Goto type alias
([#4061](#4061))
([dc83385](dc83385))
* **lsp:** Goto type definition
([#4029](#4029))
([8bb4ddf](8bb4ddf))
* **lsp:** Re-add code lens feature with improved performance
([#3829](#3829))
([8f5cd6c](8f5cd6c))
* Optimize array ops for arrays of structs
([#4027](#4027))
([c9ec0d8](c9ec0d8))
* Optimize logic gate ACIR-gen
([#3897](#3897))
([926460a](926460a))
* Prefer `AcirContext`-native methods for performing logic operations
([#3898](#3898))
([0ec39b8](0ec39b8))
* Remove range constraints from witnesses which are constrained to be
constants ([#3928](#3928))
([afe9c7a](afe9c7a))
* Remove truncation from brillig casts
([#3997](#3997))
([857ff97](857ff97))
* Remove truncations which can be seen to be noops using type
information ([#3953](#3953))
([cc3c2c2](cc3c2c2))
* Remove unnecessary predicate from `Lt` instruction
([#3922](#3922))
([a63433f](a63433f))
* Simplify chains of casts to be all in terms of the original `ValueId`
([#3984](#3984))
([2384d3e](2384d3e))
* Simplify multiplications by `0` or `1` in ACIR gen
([#3924](#3924))
([e58844d](e58844d))
* Support for u128
([#3913](#3913))
([b4911dc](b4911dc))
* Support printing more types
([#4071](#4071))
([f5c4632](f5c4632))
* Sync `aztec-packages`
([#4011](#4011))
([fee2452](fee2452))
* Sync commits from `aztec-packages`
([#4068](#4068))
([7a8f3a3](7a8f3a3))
* Use singleton `WasmBlackBoxFunctionSolver` in `noir_js`
([#3966](#3966))
([10b28de](10b28de))


### Bug Fixes

* Acir gen doesn't panic on unsupported BB function
([#3866](#3866))
([34fd978](34fd978))
* Allow abi encoding arrays of structs from JS
([#3867](#3867))
([9b713f8](9b713f8))
* Allow abi encoding tuples from JS
([#3894](#3894))
([f7fa181](f7fa181))
* Allow ast when macro errors
([#4005](#4005))
([efccec3](efccec3))
* Allow lsp to run inside of a docker container
([#3876](#3876))
([2529977](2529977))
* Bit-shifts for signed integers
([#3890](#3890))
([6ddd98a](6ddd98a))
* Checks for cyclic dependencies
([#3699](#3699))
([642011a](642011a))
* **debugger:** Crash when stepping through locations spanning multiple
lines ([#3920](#3920))
([223e860](223e860))
* Don't fail if no tests and the user didn't provide a pattern
([#3864](#3864))
([decbd0f](decbd0f))
* Fix advisory issue in cargo-deny
([#4077](#4077))
([19baea0](19baea0))
* Fixing dark mode background on the CTA button
([#3882](#3882))
([57eae42](57eae42))
* Fixup exports from `noir_wasm`
([#4022](#4022))
([358cdd2](358cdd2))
* Handle multiple imports in the same file
([#3903](#3903))
([219423e](219423e))
* Hoist constraints on inputs to top of program
([#4076](#4076))
([447aa34](447aa34))
* Implement missing codegen for `BlackBoxFunc::EcdsaSecp256r1` in
brillig ([#3943](#3943))
([2c5eceb](2c5eceb))
* Improve `nargo test` output
([#3973](#3973))
([3ab5ff4](3ab5ff4))
* Make `constant_to_radix` emit a slice instead of an array
([#4049](#4049))
([5cdb1d0](5cdb1d0))
* Operator overloading & static trait method references resolving to
generic impls ([#3967](#3967))
([f1de8fa](f1de8fa))
* Preserve brillig entrypoint functions without arguments
([#3951](#3951))
([1111465](1111465))
* Prevent `Instruction::Constrain`s for non-primitive types
([#3916](#3916))
([467948f](467948f))
* Remove panic for adding an invalid crate name in wasm compiler
([#3977](#3977))
([7a1baa5](7a1baa5))
* Return error rather instead of panicking on invalid circuit
([#3976](#3976))
([67201bf](67201bf))
* Search all levels of struct nesting before codegenning primitive types
([#3970](#3970))
([13ae014](13ae014))
* Update generics docs to mention we have traits now
([#3980](#3980))
([c2acdf1](c2acdf1))


### Miscellaneous Chores

* Ban nested slices
([#4018](#4018))
([f8a1fb7](f8a1fb7))
* Remove circuit methods from noir_wasm
([#3869](#3869))
([12d884e](12d884e))
* Rename Arithmetic opcode to AssertZero
([#3840](#3840))
([836f171](836f171))
</details>

<details><summary>0.39.0</summary>

## [0.39.0](v0.38.0...v0.39.0)
(2024-01-22)


### ⚠ BREAKING CHANGES

* Breaking changes from aztec-packages
([#3955](#3955))
* Rename Arithmetic opcode to AssertZero
([#3840](#3840))
* Remove unused methods on ACIR opcodes
([#3841](#3841))
* Remove partial backend feature
([#3805](#3805))

### Features

* Aztec-packages
([#3754](#3754))
([c043265](c043265))
* Breaking changes from aztec-packages
([#3955](#3955))
([5be049e](5be049e))
* Remove range constraints from witnesses which are constrained to be
constants ([#3928](#3928))
([afe9c7a](afe9c7a))
* Speed up transformation of debug messages
([#3815](#3815))
([2a8af1e](2a8af1e))
* Sync `aztec-packages`
([#4011](#4011))
([fee2452](fee2452))
* Sync commits from `aztec-packages`
([#4068](#4068))
([7a8f3a3](7a8f3a3))


### Bug Fixes

* Deserialize odd length hex literals
([#3747](#3747))
([4000fb2](4000fb2))
* Return error rather instead of panicking on invalid circuit
([#3976](#3976))
([67201bf](67201bf))


### Miscellaneous Chores

* Remove partial backend feature
([#3805](#3805))
([0383100](0383100))
* Remove unused methods on ACIR opcodes
([#3841](#3841))
([9e5d0e8](9e5d0e8))
* Rename Arithmetic opcode to AssertZero
([#3840](#3840))
([836f171](836f171))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Co-authored-by: TomAFrench <tom@tomfren.ch>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Print renders incorrect values when passing multiple structs
3 participants