diff --git a/.noir-sync-commit b/.noir-sync-commit index 3b7cd7252e3..f4fc7bffffb 100644 --- a/.noir-sync-commit +++ b/.noir-sync-commit @@ -1 +1 @@ -52bcb0f24b27090e812611c23ed326a541d37153 +f9abf724abd674ea4ccb342a770d237c70864ee1 diff --git a/noir/noir-repo/.github/workflows/cache-cleanup.yml b/noir/noir-repo/.github/workflows/cache-cleanup.yml index cf2b0ec413e..bb05c5454e5 100644 --- a/noir/noir-repo/.github/workflows/cache-cleanup.yml +++ b/noir/noir-repo/.github/workflows/cache-cleanup.yml @@ -12,7 +12,7 @@ on: jobs: cleanup: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Cleanup run: | diff --git a/noir/noir-repo/.github/workflows/deny.yml b/noir/noir-repo/.github/workflows/deny.yml index 8ae7d03e076..11dbc3eef4b 100644 --- a/noir/noir-repo/.github/workflows/deny.yml +++ b/noir/noir-repo/.github/workflows/deny.yml @@ -18,7 +18,7 @@ concurrency: deny-${{ github.head_ref || github.run_id }} jobs: deny: name: deny - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - uses: EmbarkStudios/cargo-deny-action@v1 diff --git a/noir/noir-repo/.github/workflows/docs-dead-links.yml b/noir/noir-repo/.github/workflows/docs-dead-links.yml index 40e948fe2c1..b46c5393f8d 100644 --- a/noir/noir-repo/.github/workflows/docs-dead-links.yml +++ b/noir/noir-repo/.github/workflows/docs-dead-links.yml @@ -13,7 +13,7 @@ concurrency: jobs: markdown-link-check: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@master - uses: gaurav-nelson/github-action-markdown-link-check@v1 diff --git a/noir/noir-repo/.github/workflows/docs-pr.yml b/noir/noir-repo/.github/workflows/docs-pr.yml index 78abb8252b3..fdd4d25f5ae 100644 --- a/noir/noir-repo/.github/workflows/docs-pr.yml +++ b/noir/noir-repo/.github/workflows/docs-pr.yml @@ -5,7 +5,7 @@ on: jobs: add_label: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 outputs: has_label: ${{ steps.check-labels.outputs.result }} steps: @@ -49,7 +49,7 @@ jobs: } build_preview: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout code uses: actions/checkout@v4 @@ -93,7 +93,7 @@ jobs: deploy_preview: needs: [build_preview, add_label] - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 permissions: pull-requests: write if: needs.add_label.outputs.has_label == 'true' @@ -121,7 +121,7 @@ jobs: add_comment: needs: [deploy_preview] - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 permissions: pull-requests: write steps: diff --git a/noir/noir-repo/.github/workflows/formatting.yml b/noir/noir-repo/.github/workflows/formatting.yml index ab92d452c79..f8ebd53dc70 100644 --- a/noir/noir-repo/.github/workflows/formatting.yml +++ b/noir/noir-repo/.github/workflows/formatting.yml @@ -15,7 +15,7 @@ concurrency: jobs: clippy: name: cargo clippy - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 env: RUSTFLAGS: -Dwarnings @@ -41,7 +41,7 @@ jobs: rustfmt: name: cargo fmt - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 env: RUSTFLAGS: -Dwarnings @@ -67,7 +67,7 @@ jobs: eslint: name: eslint - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -115,7 +115,7 @@ jobs: nargo_fmt: needs: [build-nargo] name: Nargo fmt - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: diff --git a/noir/noir-repo/.github/workflows/publish-acvm.yml b/noir/noir-repo/.github/workflows/publish-acvm.yml index feb4d4216c3..fb2e2001e40 100644 --- a/noir/noir-repo/.github/workflows/publish-acvm.yml +++ b/noir/noir-repo/.github/workflows/publish-acvm.yml @@ -10,7 +10,7 @@ on: jobs: publish: name: Publish in order - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout sources uses: actions/checkout@v4 diff --git a/noir/noir-repo/.github/workflows/publish-docs.yml b/noir/noir-repo/.github/workflows/publish-docs.yml index 8896e613608..16959256d2a 100644 --- a/noir/noir-repo/.github/workflows/publish-docs.yml +++ b/noir/noir-repo/.github/workflows/publish-docs.yml @@ -10,7 +10,7 @@ on: jobs: publish-docs: name: Publish docs - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout release branch diff --git a/noir/noir-repo/.github/workflows/publish-es-packages.yml b/noir/noir-repo/.github/workflows/publish-es-packages.yml index 682fed69c7b..e629ae1f133 100644 --- a/noir/noir-repo/.github/workflows/publish-es-packages.yml +++ b/noir/noir-repo/.github/workflows/publish-es-packages.yml @@ -16,7 +16,7 @@ run-name: Publish ES Packages from ${{ inputs.noir-ref }} under @${{ inputs.npm- jobs: build-noirc_abi_wasm: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout Noir repo uses: actions/checkout@v4 @@ -50,7 +50,7 @@ jobs: retention-days: 10 build-noir_wasm: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout sources uses: actions/checkout@v4 @@ -87,7 +87,7 @@ jobs: retention-days: 3 build-acvm_js: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout sources uses: actions/checkout@v4 @@ -121,7 +121,7 @@ jobs: retention-days: 3 publish-es-packages: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: [build-acvm_js, build-noirc_abi_wasm, build-noir_wasm] steps: - name: Checkout sources diff --git a/noir/noir-repo/.github/workflows/publish-nightly.yml b/noir/noir-repo/.github/workflows/publish-nightly.yml index f5c013883bb..2eef9ab60f7 100644 --- a/noir/noir-repo/.github/workflows/publish-nightly.yml +++ b/noir/noir-repo/.github/workflows/publish-nightly.yml @@ -7,7 +7,7 @@ on: jobs: dispatch-publish-es: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Dispatch to publish-nargo uses: benc-uk/workflow-dispatch@v1 diff --git a/noir/noir-repo/.github/workflows/pull-request-title.yml b/noir/noir-repo/.github/workflows/pull-request-title.yml index 7e9b729da28..41922bd32ab 100644 --- a/noir/noir-repo/.github/workflows/pull-request-title.yml +++ b/noir/noir-repo/.github/workflows/pull-request-title.yml @@ -15,7 +15,7 @@ permissions: jobs: conventional-title: name: Validate PR title is Conventional Commit - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Check title if: github.event_name == 'pull_request_target' @@ -30,7 +30,7 @@ jobs: force-push-comment: name: Warn external contributors about force-pushing - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 if: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != 'noir-lang/noir' }} permissions: pull-requests: write diff --git a/noir/noir-repo/.github/workflows/recrawler.yml b/noir/noir-repo/.github/workflows/recrawler.yml index ee832e273a1..808e5819353 100644 --- a/noir/noir-repo/.github/workflows/recrawler.yml +++ b/noir/noir-repo/.github/workflows/recrawler.yml @@ -7,7 +7,7 @@ on: jobs: algolia_recrawl: name: Algolia Recrawl - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Algolia crawler creation and crawl uses: algolia/algoliasearch-crawler-github-actions@v1.1.0 diff --git a/noir/noir-repo/.github/workflows/release.yml b/noir/noir-repo/.github/workflows/release.yml index 59c3d9a1415..bbe9a7fff62 100644 --- a/noir/noir-repo/.github/workflows/release.yml +++ b/noir/noir-repo/.github/workflows/release.yml @@ -11,7 +11,7 @@ jobs: outputs: release-pr: ${{ steps.release.outputs.pr }} tag-name: ${{ steps.release.outputs.tag_name }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Run release-please id: release @@ -23,7 +23,7 @@ jobs: name: Update acvm workspace package versions needs: [release-please] if: ${{ needs.release-please.outputs.release-pr }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout release branch uses: actions/checkout@v4 @@ -66,7 +66,7 @@ jobs: name: Update docs needs: [release-please, update-acvm-workspace-package-versions] if: ${{ needs.release-please.outputs.release-pr }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout release branch @@ -110,7 +110,7 @@ jobs: release-end: name: Release End - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 # We want this job to always run (even if the dependant jobs fail) as we need apply changes to the sticky comment. if: ${{ always() }} @@ -145,7 +145,7 @@ jobs: name: Build binaries needs: [release-please] if: ${{ needs.release-please.outputs.tag-name }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Dispatch to publish workflow uses: benc-uk/workflow-dispatch@v1 @@ -160,7 +160,7 @@ jobs: name: Publish ES packages needs: [release-please] if: ${{ needs.release-please.outputs.tag-name }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Dispatch to publish-es-packages uses: benc-uk/workflow-dispatch@v1 @@ -174,7 +174,7 @@ jobs: name: Publish acvm needs: [release-please] if: ${{ needs.release-please.outputs.tag-name }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Dispatch to publish-acvm diff --git a/noir/noir-repo/.github/workflows/reports.yml b/noir/noir-repo/.github/workflows/reports.yml index 8d18e378d34..24a0ce8951f 100644 --- a/noir/noir-repo/.github/workflows/reports.yml +++ b/noir/noir-repo/.github/workflows/reports.yml @@ -8,7 +8,7 @@ on: jobs: build-nargo: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout Noir repo @@ -42,7 +42,7 @@ jobs: compare_gates_reports: name: Circuit sizes needs: [build-nargo] - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 permissions: pull-requests: write @@ -93,7 +93,7 @@ jobs: compare_brillig_bytecode_size_reports: name: Brillig bytecode sizes needs: [build-nargo] - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 permissions: pull-requests: write @@ -142,7 +142,7 @@ jobs: compare_brillig_execution_reports: name: Brillig execution trace sizes needs: [build-nargo] - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 permissions: pull-requests: write @@ -191,7 +191,7 @@ jobs: generate_memory_report: name: Peak memory usage needs: [build-nargo] - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 permissions: pull-requests: write @@ -237,7 +237,7 @@ jobs: generate_compilation_report: name: Compilation time needs: [build-nargo] - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 permissions: pull-requests: write diff --git a/noir/noir-repo/.github/workflows/spellcheck.yml b/noir/noir-repo/.github/workflows/spellcheck.yml index 83d67325775..2b9a1461231 100644 --- a/noir/noir-repo/.github/workflows/spellcheck.yml +++ b/noir/noir-repo/.github/workflows/spellcheck.yml @@ -10,7 +10,7 @@ concurrency: jobs: code: name: Code - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout sources uses: actions/checkout@v4 @@ -25,7 +25,7 @@ jobs: docs: name: Documentation - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout sources uses: actions/checkout@v4 diff --git a/noir/noir-repo/.github/workflows/test-js-packages.yml b/noir/noir-repo/.github/workflows/test-js-packages.yml index 36ece11b1bf..41a7008efc0 100644 --- a/noir/noir-repo/.github/workflows/test-js-packages.yml +++ b/noir/noir-repo/.github/workflows/test-js-packages.yml @@ -14,7 +14,7 @@ concurrency: jobs: yarn-lock: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -60,7 +60,7 @@ jobs: retention-days: 3 build-noirc-abi: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -92,7 +92,7 @@ jobs: retention-days: 10 build-noir-wasm: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -127,7 +127,7 @@ jobs: retention-days: 3 build-acvm-js: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -161,7 +161,7 @@ jobs: test-acvm_js-node: needs: [build-acvm-js] name: ACVM JS (Node.js) - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -183,7 +183,7 @@ jobs: test-acvm_js-browser: needs: [build-acvm-js] name: ACVM JS (Browser) - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -208,7 +208,7 @@ jobs: test-noirc-abi: needs: [build-noirc-abi] name: noirc_abi - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -236,7 +236,7 @@ jobs: test-noir-js: needs: [build-nargo, build-acvm-js, build-noirc-abi] name: Noir JS - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -283,7 +283,7 @@ jobs: test-noir-wasm: needs: [build-noir-wasm, build-nargo] name: noir_wasm - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -327,7 +327,7 @@ jobs: test-noir-codegen: needs: [build-acvm-js, build-noirc-abi, build-nargo] name: noir_codegen - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -374,7 +374,7 @@ jobs: test-integration-node: name: Integration Tests (Node) - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: [build-acvm-js, build-noir-wasm, build-nargo, build-noirc-abi] timeout-minutes: 30 @@ -435,7 +435,7 @@ jobs: test-integration-browser: name: Integration Tests (Browser) - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: [build-acvm-js, build-noir-wasm, build-noirc-abi] timeout-minutes: 30 @@ -480,7 +480,7 @@ jobs: test-examples: name: Example scripts - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: [build-nargo] timeout-minutes: 30 @@ -523,7 +523,7 @@ jobs: critical-library-list: name: Load critical library list - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 outputs: libraries: ${{ steps.get_critical_libraries.outputs.libraries }} @@ -542,7 +542,7 @@ jobs: external-repo-checks: needs: [build-nargo, critical-library-list] - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 # Only run when 'run-external-checks' label is present if: contains(github.event.pull_request.labels.*.name, 'run-external-checks') timeout-minutes: 30 @@ -599,7 +599,7 @@ jobs: # This allows us to add/remove test jobs without having to update the required workflows. tests-end: name: End - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 # We want this job to always run (even if the dependant jobs fail) as we want this job to fail rather than skipping. if: ${{ always() }} needs: diff --git a/noir/noir-repo/.github/workflows/test-rust-workspace-msrv.yml b/noir/noir-repo/.github/workflows/test-rust-workspace-msrv.yml index ae016169830..662d5a39720 100644 --- a/noir/noir-repo/.github/workflows/test-rust-workspace-msrv.yml +++ b/noir/noir-repo/.github/workflows/test-rust-workspace-msrv.yml @@ -21,7 +21,7 @@ concurrency: jobs: build-test-artifacts: name: Build test artifacts - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -62,7 +62,7 @@ jobs: run-tests: name: "Run tests (partition ${{matrix.partition}})" - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: [build-test-artifacts] strategy: fail-fast: false @@ -95,7 +95,7 @@ jobs: # This allows us to add/remove test jobs without having to update the required workflows. tests-end: name: Rust End - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 # We want this job to always run (even if the dependant jobs fail) as we want this job to fail rather than skipping. if: ${{ always() }} needs: diff --git a/noir/noir-repo/.github/workflows/test-rust-workspace.yml b/noir/noir-repo/.github/workflows/test-rust-workspace.yml index 1f3ee5e2268..1053d985d88 100644 --- a/noir/noir-repo/.github/workflows/test-rust-workspace.yml +++ b/noir/noir-repo/.github/workflows/test-rust-workspace.yml @@ -15,7 +15,7 @@ concurrency: jobs: build-test-artifacts: name: Build test artifacts - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -49,7 +49,7 @@ jobs: run-tests: name: "Run tests (partition ${{matrix.partition}})" - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: [build-test-artifacts] strategy: fail-fast: false @@ -82,7 +82,7 @@ jobs: # This allows us to add/remove test jobs without having to update the required workflows. tests-end: name: Rust End - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 # We want this job to always run (even if the dependant jobs fail) as we want this job to fail rather than skipping. if: ${{ always() }} needs: diff --git a/noir/noir-repo/Cargo.lock b/noir/noir-repo/Cargo.lock index 2a6f10dcc19..cf96770e9b8 100644 --- a/noir/noir-repo/Cargo.lock +++ b/noir/noir-repo/Cargo.lock @@ -2883,6 +2883,7 @@ dependencies = [ "noirc_frontend", "semver", "serde", + "tempfile", "test-case", "thiserror", "toml 0.7.8", diff --git a/noir/noir-repo/acvm-repo/acvm/src/compiler/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/compiler/mod.rs index e32c0665c0f..4ad4952c5cc 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/compiler/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/compiler/mod.rs @@ -82,6 +82,11 @@ pub fn compile( acir: Circuit, expression_width: ExpressionWidth, ) -> (Circuit, AcirTransformationMap) { + if MAX_OPTIMIZER_PASSES == 0 { + let acir_opcode_positions = (0..acir.opcodes.len()).collect::>(); + let transformation_map = AcirTransformationMap::new(&acir_opcode_positions); + return (acir, transformation_map); + } let mut pass = 0; let mut prev_opcodes_hash = fxhash::hash64(&acir.opcodes); let mut prev_acir = acir; diff --git a/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs b/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs index f49cd61e813..43e32101cc5 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs @@ -41,7 +41,9 @@ impl MergeExpressionsOptimizer { self.resolved_blocks.clear(); // Keep track, for each witness, of the gates that use it - let circuit_inputs = circuit.circuit_arguments(); + let circuit_io: BTreeSet = + circuit.circuit_arguments().union(&circuit.public_inputs().0).cloned().collect(); + let mut used_witness: BTreeMap> = BTreeMap::new(); for (i, opcode) in circuit.opcodes.iter().enumerate() { let witnesses = self.witness_inputs(opcode); @@ -49,8 +51,8 @@ impl MergeExpressionsOptimizer { self.resolved_blocks.insert(*block_id, witnesses.clone()); } for w in witnesses { - // We do not simplify circuit inputs - if !circuit_inputs.contains(&w) { + // We do not simplify circuit inputs and outputs + if !circuit_io.contains(&w) { used_witness.entry(w).or_default().insert(i); } } @@ -102,7 +104,7 @@ impl MergeExpressionsOptimizer { let mut witness_list = CircuitSimulator::expr_wit(&expr_use); witness_list.extend(CircuitSimulator::expr_wit(&expr_define)); for w2 in witness_list { - if !circuit_inputs.contains(&w2) { + if !circuit_io.contains(&w2) { used_witness.entry(w2).and_modify(|v| { v.insert(target); v.remove(&source); @@ -326,6 +328,50 @@ mod tests { check_circuit(circuit); } + #[test] + fn does_not_eliminate_witnesses_returned_from_circuit() { + let opcodes = vec![ + Opcode::AssertZero(Expression { + mul_terms: vec![(FieldElement::from(-1i128), Witness(0), Witness(0))], + linear_combinations: vec![(FieldElement::from(1i128), Witness(1))], + q_c: FieldElement::zero(), + }), + Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (FieldElement::from(-1i128), Witness(1)), + (FieldElement::from(1i128), Witness(2)), + ], + q_c: FieldElement::zero(), + }), + ]; + // Witness(1) could be eliminated because it's only used by 2 opcodes. + + let mut private_parameters = BTreeSet::new(); + private_parameters.insert(Witness(0)); + + let mut return_values = BTreeSet::new(); + return_values.insert(Witness(1)); + return_values.insert(Witness(2)); + + let circuit = Circuit { + current_witness_index: 2, + expression_width: ExpressionWidth::Bounded { width: 4 }, + opcodes, + private_parameters, + public_parameters: PublicInputs::default(), + return_values: PublicInputs(return_values), + assert_messages: Default::default(), + }; + + let mut merge_optimizer = MergeExpressionsOptimizer::new(); + let acir_opcode_positions = vec![0; 20]; + let (opcodes, _) = + merge_optimizer.eliminate_intermediate_variable(&circuit, acir_opcode_positions); + + assert_eq!(opcodes.len(), 2); + } + #[test] fn does_not_attempt_to_merge_into_previous_opcodes() { let opcodes = vec![ diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index 20c12a72fc0..f9188cca700 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -359,7 +359,6 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { pub fn solve_opcode(&mut self) -> ACVMStatus { let opcode = &self.opcodes[self.instruction_pointer]; - let resolution = match opcode { Opcode::AssertZero(expr) => ExpressionSolver::solve(&mut self.witness_map, expr), Opcode::BlackBoxFuncCall(bb_func) => blackbox::solve( diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs index 0de94a89be5..884db763698 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs @@ -15,7 +15,7 @@ impl<'a> Parser<'a> { typ } else { self.expected_label(ParsingRuleLabel::Type); - self.unspecified_type_at_previous_token_end() + UnresolvedTypeData::Error.with_span(self.span_at_previous_token_end()) } } @@ -660,6 +660,14 @@ mod tests { assert!(unconstrained); } + #[test] + fn parses_function_type_with_colon_in_parameter() { + let src = "fn(value: T) -> Field"; + let mut parser = Parser::for_str(src); + let _ = parser.parse_type_or_error(); + assert!(!parser.errors.is_empty()); + } + #[test] fn parses_trait_as_type_no_generics() { let src = "impl foo::Bar"; diff --git a/noir/noir-repo/docs/docs/index.mdx b/noir/noir-repo/docs/docs/index.mdx index a6bd306f91d..5c116a73b3f 100644 --- a/noir/noir-repo/docs/docs/index.mdx +++ b/noir/noir-repo/docs/docs/index.mdx @@ -21,8 +21,17 @@ sidebar_position: 0 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; - -Noir Logo +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + + Noir is an open-source Domain-Specific Language for safe and seamless construction of privacy-preserving Zero-Knowledge programs, requiring no previous knowledge on the underlying mathematics or cryptography. diff --git a/noir/noir-repo/docs/docs/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/docs/noir/modules_packages_crates/workspaces.md index 513497f12bf..2fbf10aec52 100644 --- a/noir/noir-repo/docs/docs/noir/modules_packages_crates/workspaces.md +++ b/noir/noir-repo/docs/docs/noir/modules_packages_crates/workspaces.md @@ -33,10 +33,14 @@ members = ["crates/a", "crates/b"] default-member = "crates/a" ``` -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. +`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. The `--package` option can be used to limit +the scope of some commands to a specific member of the workspace; otherwise these commands run on the package nearest on the path to the +current directory where `nargo` was invoked. `default-member` indicates which package various commands process by default. Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. + +Please note that nesting regular packages is not supported: certain commands work on the workspace level and will use the topmost Nargo.toml file they can find on the path; unless this is a workspace configuration with `members`, the command might run on some unintended package. diff --git a/noir/noir-repo/docs/docusaurus.config.ts b/noir/noir-repo/docs/docusaurus.config.ts index c53d11e3373..eee4e7f8236 100644 --- a/noir/noir-repo/docs/docusaurus.config.ts +++ b/noir/noir-repo/docs/docusaurus.config.ts @@ -57,8 +57,8 @@ export default { navbar: { logo: { alt: 'Noir Logo', - src: 'img/logo.svg', - srcDark: 'img/logoDark.svg', + src: 'img/logoDark.svg', + srcDark: 'img/logo.svg', href: '/', }, items: [ diff --git a/noir/noir-repo/docs/static/img/favicon.ico b/noir/noir-repo/docs/static/img/favicon.ico index 1c85cef482e..0abffba22ef 100644 Binary files a/noir/noir-repo/docs/static/img/favicon.ico and b/noir/noir-repo/docs/static/img/favicon.ico differ diff --git a/noir/noir-repo/docs/static/img/homepage_header_pic.png b/noir/noir-repo/docs/static/img/homepage_header_pic.png index d629e202232..f6bdd5378f6 100644 Binary files a/noir/noir-repo/docs/static/img/homepage_header_pic.png and b/noir/noir-repo/docs/static/img/homepage_header_pic.png differ diff --git a/noir/noir-repo/docs/static/img/logo.png b/noir/noir-repo/docs/static/img/logo.png index 83d3a66f2b1..0df14cf4f00 100644 Binary files a/noir/noir-repo/docs/static/img/logo.png and b/noir/noir-repo/docs/static/img/logo.png differ diff --git a/noir/noir-repo/docs/static/img/logo.svg b/noir/noir-repo/docs/static/img/logo.svg index 8095d6a169d..f6fadf87bcb 100644 --- a/noir/noir-repo/docs/static/img/logo.svg +++ b/noir/noir-repo/docs/static/img/logo.svg @@ -1,29 +1,14 @@ - - - - - - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/noir/noir-repo/docs/static/img/logoDark.png b/noir/noir-repo/docs/static/img/logoDark.png new file mode 100644 index 00000000000..25d554c486c Binary files /dev/null and b/noir/noir-repo/docs/static/img/logoDark.png differ diff --git a/noir/noir-repo/docs/static/img/logoDark.svg b/noir/noir-repo/docs/static/img/logoDark.svg index dee9f27a6a9..ac0f9897b30 100644 --- a/noir/noir-repo/docs/static/img/logoDark.svg +++ b/noir/noir-repo/docs/static/img/logoDark.svg @@ -1,29 +1,13 @@ - - - - - - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.36.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.36.0/index.mdx index a6bd306f91d..5c116a73b3f 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.36.0/index.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v0.36.0/index.mdx @@ -21,8 +21,17 @@ sidebar_position: 0 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; - -Noir Logo +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + + Noir is an open-source Domain-Specific Language for safe and seamless construction of privacy-preserving Zero-Knowledge programs, requiring no previous knowledge on the underlying mathematics or cryptography. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.37.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.37.0/index.mdx index a6bd306f91d..5c116a73b3f 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.37.0/index.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v0.37.0/index.mdx @@ -21,8 +21,17 @@ sidebar_position: 0 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; - -Noir Logo +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + + Noir is an open-source Domain-Specific Language for safe and seamless construction of privacy-preserving Zero-Knowledge programs, requiring no previous knowledge on the underlying mathematics or cryptography. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/index.mdx index a6bd306f91d..5c116a73b3f 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/index.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/index.mdx @@ -21,8 +21,17 @@ sidebar_position: 0 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; - -Noir Logo +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + + Noir is an open-source Domain-Specific Language for safe and seamless construction of privacy-preserving Zero-Knowledge programs, requiring no previous knowledge on the underlying mathematics or cryptography. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.39.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.39.0/index.mdx index a6bd306f91d..5c116a73b3f 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.39.0/index.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v0.39.0/index.mdx @@ -21,8 +21,17 @@ sidebar_position: 0 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; - -Noir Logo +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + + Noir is an open-source Domain-Specific Language for safe and seamless construction of privacy-preserving Zero-Knowledge programs, requiring no previous knowledge on the underlying mathematics or cryptography. diff --git a/noir/noir-repo/docs/versioned_docs/version-v1.0.0-beta.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v1.0.0-beta.0/index.mdx index a6bd306f91d..5c116a73b3f 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v1.0.0-beta.0/index.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v1.0.0-beta.0/index.mdx @@ -21,8 +21,17 @@ sidebar_position: 0 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; - -Noir Logo +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + + Noir is an open-source Domain-Specific Language for safe and seamless construction of privacy-preserving Zero-Knowledge programs, requiring no previous knowledge on the underlying mathematics or cryptography. diff --git a/noir/noir-repo/noir-logo.png b/noir/noir-repo/noir-logo.png index eabb163ad73..0abffba22ef 100644 Binary files a/noir/noir-repo/noir-logo.png and b/noir/noir-repo/noir-logo.png differ diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs index 9059f1dd8e8..c8695a8f626 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs @@ -4,33 +4,25 @@ use clap::Args; use fm::FileManager; use iter_extended::btree_map; use nargo::{ - errors::CompileError, - insert_all_files_for_workspace_into_file_manager, - ops::report_errors, - package::{CrateName, Package}, - parse_all, prepare_package, + errors::CompileError, insert_all_files_for_workspace_into_file_manager, ops::report_errors, + package::Package, parse_all, prepare_package, }; -use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use nargo_toml::{get_package_manifest, resolve_workspace_from_toml}; use noirc_abi::{AbiParameter, AbiType, MAIN_RETURN_NAME}; use noirc_driver::{ check_crate, compute_function_abi, CompileOptions, CrateId, NOIR_ARTIFACT_VERSION_STRING, }; use noirc_frontend::hir::{Context, ParsedFiles}; -use super::fs::write_to_file; use super::NargoConfig; +use super::{fs::write_to_file, PackageOptions}; /// Checks the constraint system for errors #[derive(Debug, Clone, Args)] #[clap(visible_alias = "c")] pub(crate) struct CheckCommand { - /// The name of the package to check - #[clap(long, conflicts_with = "workspace")] - package: Option, - - /// Check all packages in the workspace - #[clap(long, conflicts_with = "package")] - workspace: bool, + #[clap(flatten)] + pub(super) package_options: PackageOptions, /// Force overwrite of existing files #[clap(long = "overwrite")] @@ -42,9 +34,7 @@ pub(crate) struct CheckCommand { pub(crate) fn run(args: CheckCommand, config: NargoConfig) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; - let default_selection = - if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; - let selection = args.package.map_or(default_selection, PackageSelection::Selected); + let selection = args.package_options.package_selection(); let workspace = resolve_workspace_from_toml( &toml_path, selection, diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs index f134374f89e..2ecf6959a94 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -5,7 +5,7 @@ use std::time::Duration; use acvm::acir::circuit::ExpressionWidth; use fm::FileManager; use nargo::ops::{collect_errors, compile_contract, compile_program, report_errors}; -use nargo::package::{CrateName, Package}; +use nargo::package::Package; use nargo::workspace::Workspace; use nargo::{insert_all_files_for_workspace_into_file_manager, parse_all}; use nargo_toml::{ @@ -23,19 +23,14 @@ use notify_debouncer_full::new_debouncer; use crate::errors::CliError; use super::fs::program::{read_program_from_file, save_contract_to_file, save_program_to_file}; -use super::NargoConfig; +use super::{NargoConfig, PackageOptions}; use rayon::prelude::*; /// Compile the program and its secret execution trace into ACIR format #[derive(Debug, Clone, Args)] pub(crate) struct CompileCommand { - /// The name of the package to compile - #[clap(long, conflicts_with = "workspace")] - package: Option, - - /// Compile all packages in the workspace. - #[clap(long, conflicts_with = "package")] - workspace: bool, + #[clap(flatten)] + pub(super) package_options: PackageOptions, #[clap(flatten)] compile_options: CompileOptions, @@ -46,10 +41,7 @@ pub(crate) struct CompileCommand { } pub(crate) fn run(args: CompileCommand, config: NargoConfig) -> Result<(), CliError> { - let default_selection = - if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; - let selection = args.package.map_or(default_selection, PackageSelection::Selected); - + let selection = args.package_options.package_selection(); let workspace = read_workspace(&config.program_dir, selection)?; if args.watch { diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs index e837f297475..f4dd607a53e 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -38,7 +38,7 @@ pub(crate) struct DebugCommand { /// The name of the package to execute #[clap(long)] - package: Option, + pub(super) package: Option, #[clap(flatten)] compile_options: CompileOptions, diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs index fa95d3123c6..81aca16846b 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -8,8 +8,8 @@ use clap::Args; use nargo::constants::PROVER_INPUT_FILE; use nargo::errors::try_to_diagnose_runtime_error; use nargo::foreign_calls::DefaultForeignCallExecutor; -use nargo::package::{CrateName, Package}; -use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use nargo::package::Package; +use nargo_toml::{get_package_manifest, resolve_workspace_from_toml}; use noirc_abi::input_parser::{Format, InputValue}; use noirc_abi::InputMap; use noirc_artifacts::debug::DebugArtifact; @@ -17,7 +17,7 @@ use noirc_driver::{CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING use super::compile_cmd::compile_workspace_full; use super::fs::{inputs::read_inputs_from_file, witness::save_witness_to_dir}; -use super::NargoConfig; +use super::{NargoConfig, PackageOptions}; use crate::cli::fs::program::read_program_from_file; use crate::errors::CliError; @@ -34,13 +34,8 @@ pub(crate) struct ExecuteCommand { #[clap(long, short, default_value = PROVER_INPUT_FILE)] prover_name: String, - /// The name of the package to execute - #[clap(long, conflicts_with = "workspace")] - package: Option, - - /// Execute all packages in the workspace - #[clap(long, conflicts_with = "package")] - workspace: bool, + #[clap(flatten)] + pub(super) package_options: PackageOptions, #[clap(flatten)] compile_options: CompileOptions, @@ -52,9 +47,7 @@ pub(crate) struct ExecuteCommand { pub(crate) fn run(args: ExecuteCommand, config: NargoConfig) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; - let default_selection = - if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; - let selection = args.package.map_or(default_selection, PackageSelection::Selected); + let selection = args.package_options.package_selection(); let workspace = resolve_workspace_from_toml( &toml_path, selection, diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/export_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/export_cmd.rs index c3752db7fbd..cb92b987c4e 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/export_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/export_cmd.rs @@ -10,13 +10,11 @@ use nargo::package::Package; use nargo::prepare_package; use nargo::workspace::Workspace; use nargo::{insert_all_files_for_workspace_into_file_manager, parse_all}; -use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use nargo_toml::{get_package_manifest, resolve_workspace_from_toml}; use noirc_driver::{ compile_no_check, CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, }; -use noirc_frontend::graph::CrateName; - use clap::Args; use crate::errors::CliError; @@ -24,18 +22,13 @@ use crate::errors::CliError; use super::check_cmd::check_crate_and_report_errors; use super::fs::program::save_program_to_file; -use super::NargoConfig; +use super::{NargoConfig, PackageOptions}; /// Exports functions marked with #[export] attribute #[derive(Debug, Clone, Args)] pub(crate) struct ExportCommand { - /// The name of the package to compile - #[clap(long, conflicts_with = "workspace")] - package: Option, - - /// Compile all packages in the workspace - #[clap(long, conflicts_with = "package")] - workspace: bool, + #[clap(flatten)] + pub(super) package_options: PackageOptions, #[clap(flatten)] compile_options: CompileOptions, @@ -43,10 +36,7 @@ pub(crate) struct ExportCommand { pub(crate) fn run(args: ExportCommand, config: NargoConfig) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; - let default_selection = - if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; - let selection = args.package.map_or(default_selection, PackageSelection::Selected); - + let selection = args.package_options.package_selection(); let workspace = resolve_workspace_from_toml( &toml_path, selection, diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/fmt_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/fmt_cmd.rs index 66496db517c..7b29a90c5c0 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/fmt_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/fmt_cmd.rs @@ -9,7 +9,7 @@ use noirc_frontend::{hir::def_map::parse_file, parser::ParserError}; use crate::errors::CliError; -use super::NargoConfig; +use super::{NargoConfig, PackageOptions}; /// Format the Noir files in a workspace #[derive(Debug, Clone, Args)] @@ -17,15 +17,22 @@ pub(crate) struct FormatCommand { /// Run noirfmt in check mode #[arg(long)] check: bool, + + #[clap(flatten)] + pub(super) package_options: PackageOptions, } pub(crate) fn run(args: FormatCommand, config: NargoConfig) -> Result<(), CliError> { let check_mode = args.check; let toml_path = get_package_manifest(&config.program_dir)?; + let selection = match args.package_options.package_selection() { + PackageSelection::DefaultOrAll => PackageSelection::All, + other => other, + }; let workspace = resolve_workspace_from_toml( &toml_path, - PackageSelection::All, + selection, Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs index 769a1f79d81..4dab7da2ffb 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs @@ -3,11 +3,9 @@ use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; use iter_extended::vecmap; use nargo::{ - constants::PROVER_INPUT_FILE, - foreign_calls::DefaultForeignCallExecutor, - package::{CrateName, Package}, + constants::PROVER_INPUT_FILE, foreign_calls::DefaultForeignCallExecutor, package::Package, }; -use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use nargo_toml::{get_package_manifest, resolve_workspace_from_toml}; use noirc_abi::input_parser::Format; use noirc_artifacts::program::ProgramArtifact; use noirc_driver::{CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; @@ -20,7 +18,7 @@ use crate::{cli::fs::inputs::read_inputs_from_file, errors::CliError}; use super::{ compile_cmd::{compile_workspace_full, get_target_width}, fs::program::read_program_from_file, - NargoConfig, + NargoConfig, PackageOptions, }; /// Provides detailed information on each of a program's function (represented by a single circuit) @@ -31,13 +29,8 @@ use super::{ #[derive(Debug, Clone, Args)] #[clap(visible_alias = "i")] pub(crate) struct InfoCommand { - /// The name of the package to detail - #[clap(long, conflicts_with = "workspace")] - package: Option, - - /// Detail all packages in the workspace - #[clap(long, conflicts_with = "package")] - workspace: bool, + #[clap(flatten)] + pub(super) package_options: PackageOptions, /// Output a JSON formatted report. Changes to this format are not currently considered breaking. #[clap(long, hide = true)] @@ -56,9 +49,7 @@ pub(crate) struct InfoCommand { pub(crate) fn run(mut args: InfoCommand, config: NargoConfig) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; - let default_selection = - if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; - let selection = args.package.map_or(default_selection, PackageSelection::Selected); + let selection = args.package_options.package_selection(); let workspace = resolve_workspace_from_toml( &toml_path, selection, diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/mod.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/mod.rs index 284dd10cb88..cc72092daa1 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/mod.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/mod.rs @@ -1,8 +1,8 @@ use clap::{Args, Parser, Subcommand}; use const_format::formatcp; -use nargo_toml::find_package_root; -use noirc_driver::NOIR_ARTIFACT_VERSION_STRING; -use std::path::PathBuf; +use nargo_toml::{ManifestError, PackageSelection}; +use noirc_driver::{CrateName, NOIR_ARTIFACT_VERSION_STRING}; +use std::path::{Path, PathBuf}; use color_eyre::eyre; @@ -52,6 +52,48 @@ pub(crate) struct NargoConfig { program_dir: PathBuf, } +/// Options for commands that work on either workspace or package scope. +#[derive(Args, Clone, Debug, Default)] +pub(crate) struct PackageOptions { + /// The name of the package to run the command on. + /// By default run on the first one found moving up along the ancestors of the current directory. + #[clap(long, conflicts_with = "workspace")] + package: Option, + + /// Run on all packages in the workspace + #[clap(long, conflicts_with = "package")] + workspace: bool, +} + +impl PackageOptions { + /// Decide which package to run the command on: + /// * `package` if non-empty + /// * all packages if `workspace` is `true` + /// * otherwise the default package + pub(crate) fn package_selection(&self) -> PackageSelection { + let default_selection = + if self.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; + + self.package.clone().map_or(default_selection, PackageSelection::Selected) + } + + /// Whether we need to look for the package manifest at the workspace level. + /// If a package is specified, it might not be the current package. + fn scope(&self) -> CommandScope { + if self.workspace || self.package.is_some() { + CommandScope::Workspace + } else { + CommandScope::CurrentPackage + } + } +} + +enum CommandScope { + Workspace, + CurrentPackage, + Any, +} + #[non_exhaustive] #[derive(Subcommand, Clone, Debug)] enum NargoCommand { @@ -83,22 +125,8 @@ pub(crate) fn start_cli() -> eyre::Result<()> { } // Search through parent directories to find package root if necessary. - match &command { - NargoCommand::Check(..) - | NargoCommand::Fmt(..) - | NargoCommand::Compile(..) - | NargoCommand::Execute(..) - | NargoCommand::Export(..) - | NargoCommand::Debug(..) - | NargoCommand::Test(..) - | NargoCommand::Info(..) => { - config.program_dir = find_package_root(&config.program_dir)?; - } - NargoCommand::New(..) - | NargoCommand::Init(..) - | NargoCommand::Lsp(..) - | NargoCommand::Dap(..) - | NargoCommand::GenerateCompletionScript(..) => (), + if let Some(program_dir) = command_dir(&command, &config.program_dir)? { + config.program_dir = program_dir; } match command { @@ -127,6 +155,43 @@ pub(crate) fn start_cli() -> eyre::Result<()> { Ok(()) } +/// Some commands have package options, which we use here to decide whether to +/// alter `--program-dir` to point at a manifest, depending on whether we want +/// to work on a specific package or the entire workspace. +fn command_scope(cmd: &NargoCommand) -> CommandScope { + match &cmd { + NargoCommand::Check(cmd) => cmd.package_options.scope(), + NargoCommand::Compile(cmd) => cmd.package_options.scope(), + NargoCommand::Execute(cmd) => cmd.package_options.scope(), + NargoCommand::Export(cmd) => cmd.package_options.scope(), + NargoCommand::Test(cmd) => cmd.package_options.scope(), + NargoCommand::Info(cmd) => cmd.package_options.scope(), + NargoCommand::Fmt(cmd) => cmd.package_options.scope(), + NargoCommand::Debug(cmd) => { + if cmd.package.is_some() { + CommandScope::Workspace + } else { + CommandScope::CurrentPackage + } + } + NargoCommand::New(..) + | NargoCommand::Init(..) + | NargoCommand::Lsp(..) + | NargoCommand::Dap(..) + | NargoCommand::GenerateCompletionScript(..) => CommandScope::Any, + } +} + +/// A manifest directory we need to change into, if the command needs it. +fn command_dir(cmd: &NargoCommand, program_dir: &Path) -> Result, ManifestError> { + let workspace = match command_scope(cmd) { + CommandScope::Workspace => true, + CommandScope::CurrentPackage => false, + CommandScope::Any => return Ok(None), + }; + Ok(Some(nargo_toml::find_root(program_dir, workspace)?)) +} + #[cfg(test)] mod tests { use clap::Parser; diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs index e8c0e16ff4a..92d3c91e713 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs @@ -5,12 +5,10 @@ use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; use fm::FileManager; use nargo::{ - insert_all_files_for_workspace_into_file_manager, - ops::TestStatus, - package::{CrateName, Package}, - parse_all, prepare_package, + insert_all_files_for_workspace_into_file_manager, ops::TestStatus, package::Package, parse_all, + prepare_package, }; -use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use nargo_toml::{get_package_manifest, resolve_workspace_from_toml}; use noirc_driver::{check_crate, CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::hir::{FunctionNameMatch, ParsedFiles}; use rayon::prelude::{IntoParallelIterator, ParallelBridge, ParallelIterator}; @@ -18,7 +16,7 @@ use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; use crate::{cli::check_cmd::check_crate_and_report_errors, errors::CliError}; -use super::NargoConfig; +use super::{NargoConfig, PackageOptions}; /// Run the tests for this program #[derive(Debug, Clone, Args)] @@ -35,13 +33,8 @@ pub(crate) struct TestCommand { #[clap(long)] exact: bool, - /// The name of the package to test - #[clap(long, conflicts_with = "workspace")] - package: Option, - - /// Test all packages in the workspace - #[clap(long, conflicts_with = "package")] - workspace: bool, + #[clap(flatten)] + pub(super) package_options: PackageOptions, #[clap(flatten)] compile_options: CompileOptions, @@ -53,9 +46,7 @@ pub(crate) struct TestCommand { pub(crate) fn run(args: TestCommand, config: NargoConfig) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; - let default_selection = - if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; - let selection = args.package.map_or(default_selection, PackageSelection::Selected); + let selection = args.package_options.package_selection(); let workspace = resolve_workspace_from_toml( &toml_path, selection, diff --git a/noir/noir-repo/tooling/nargo_toml/Cargo.toml b/noir/noir-repo/tooling/nargo_toml/Cargo.toml index 2bc24153836..f5f7d7cd595 100644 --- a/noir/noir-repo/tooling/nargo_toml/Cargo.toml +++ b/noir/noir-repo/tooling/nargo_toml/Cargo.toml @@ -25,4 +25,5 @@ noirc_driver.workspace = true semver = "1.0.20" [dev-dependencies] +tempfile.workspace = true test-case.workspace = true diff --git a/noir/noir-repo/tooling/nargo_toml/src/lib.rs b/noir/noir-repo/tooling/nargo_toml/src/lib.rs index c1990dab4a6..b5c45977618 100644 --- a/noir/noir-repo/tooling/nargo_toml/src/lib.rs +++ b/noir/noir-repo/tooling/nargo_toml/src/lib.rs @@ -47,6 +47,35 @@ pub fn find_file_manifest(current_path: &Path) -> Option { } /// Returns the [PathBuf] of the directory containing the `Nargo.toml` by searching from `current_path` to the root of its [Path]. +/// When `workspace` is `true` it returns the topmost directory, when `false` the innermost one. +/// +/// Returns a [ManifestError] if no parent directories of `current_path` contain a manifest file. +pub fn find_root(current_path: &Path, workspace: bool) -> Result { + if workspace { + find_package_root(current_path) + } else { + find_file_root(current_path) + } +} + +/// Returns the [PathBuf] of the directory containing the `Nargo.toml` by searching from `current_path` to the root of its [Path], +/// returning at the innermost directory found, i.e. the one corresponding to the package that contains the `current_path`. +/// +/// Returns a [ManifestError] if no parent directories of `current_path` contain a manifest file. +pub fn find_file_root(current_path: &Path) -> Result { + match find_file_manifest(current_path) { + Some(manifest_path) => { + let package_root = manifest_path + .parent() + .expect("infallible: manifest file path can't be root directory"); + Ok(package_root.to_path_buf()) + } + None => Err(ManifestError::MissingFile(current_path.to_path_buf())), + } +} + +/// Returns the [PathBuf] of the directory containing the `Nargo.toml` by searching from `current_path` to the root of its [Path], +/// returning at the topmost directory found, i.e. the one corresponding to the entire workspace. /// /// Returns a [ManifestError] if no parent directories of `current_path` contain a manifest file. pub fn find_package_root(current_path: &Path) -> Result { @@ -60,6 +89,11 @@ pub fn find_package_root(current_path: &Path) -> Result } // TODO(#2323): We are probably going to need a "filepath utils" crate soon +/// Get the root of path, for example: +/// * `C:\foo\bar` -> `C:\foo` +/// * `//shared/foo/bar` -> `//shared/foo` +/// * `/foo` -> `/foo` +/// otherwise empty path. fn path_root(path: &Path) -> PathBuf { let mut components = path.components(); @@ -101,6 +135,7 @@ pub fn find_package_manifest( }) } } + /// Returns the [PathBuf] of the `Nargo.toml` file in the `current_path` directory. /// /// Returns a [ManifestError] if `current_path` does not contain a manifest file. @@ -490,9 +525,20 @@ pub fn resolve_workspace_from_toml( Ok(workspace) } -#[test] -fn parse_standard_toml() { - let src = r#" +#[cfg(test)] +mod tests { + use std::{ + path::{Path, PathBuf}, + str::FromStr, + }; + + use test_case::test_matrix; + + use crate::{find_root, Config, ManifestError}; + + #[test] + fn parse_standard_toml() { + let src = r#" [package] name = "test" @@ -505,49 +551,49 @@ fn parse_standard_toml() { hello = {path = "./noir_driver"} "#; - assert!(Config::try_from(String::from(src)).is_ok()); - assert!(Config::try_from(src).is_ok()); -} + assert!(Config::try_from(String::from(src)).is_ok()); + assert!(Config::try_from(src).is_ok()); + } -#[test] -fn parse_package_toml_no_deps() { - let src = r#" + #[test] + fn parse_package_toml_no_deps() { + let src = r#" [package] name = "test" authors = ["kev", "foo"] compiler_version = "*" "#; - assert!(Config::try_from(String::from(src)).is_ok()); - assert!(Config::try_from(src).is_ok()); -} + assert!(Config::try_from(String::from(src)).is_ok()); + assert!(Config::try_from(src).is_ok()); + } -#[test] -fn parse_workspace_toml() { - let src = r#" + #[test] + fn parse_workspace_toml() { + let src = r#" [workspace] members = ["a", "b"] "#; - assert!(Config::try_from(String::from(src)).is_ok()); - assert!(Config::try_from(src).is_ok()); -} + assert!(Config::try_from(String::from(src)).is_ok()); + assert!(Config::try_from(src).is_ok()); + } -#[test] -fn parse_workspace_default_member_toml() { - let src = r#" + #[test] + fn parse_workspace_default_member_toml() { + let src = r#" [workspace] members = ["a", "b"] default-member = "a" "#; - assert!(Config::try_from(String::from(src)).is_ok()); - assert!(Config::try_from(src).is_ok()); -} + assert!(Config::try_from(String::from(src)).is_ok()); + assert!(Config::try_from(src).is_ok()); + } -#[test] -fn parse_package_expression_width_toml() { - let src = r#" + #[test] + fn parse_package_expression_width_toml() { + let src = r#" [package] name = "test" version = "0.1.0" @@ -556,6 +602,124 @@ fn parse_package_expression_width_toml() { expression_width = "3" "#; - assert!(Config::try_from(String::from(src)).is_ok()); - assert!(Config::try_from(src).is_ok()); + assert!(Config::try_from(String::from(src)).is_ok()); + assert!(Config::try_from(src).is_ok()); + } + + /// Test that `find_root` handles all kinds of prefixes. + /// (It dispatches based on `workspace` to methods which handle paths differently). + #[test_matrix( + [true, false], + ["C:\\foo\\bar", "//shared/foo/bar", "/foo/bar", "bar/baz", ""] + )] + fn test_find_root_does_not_panic(workspace: bool, path: &str) { + let path = PathBuf::from_str(path).unwrap(); + let error = find_root(&path, workspace).expect_err("non-existing paths"); + assert!(matches!(error, ManifestError::MissingFile(_))); + } + + /// Test to demonstrate how `find_root` works. + #[test] + fn test_find_root_example() { + const INDENT_SIZE: usize = 4; + /// Create directories and files according to a YAML-like layout below + fn setup(layout: &str, root: &Path) { + fn is_dir(item: &str) -> bool { + !item.contains('.') + } + let mut current_dir = root.to_path_buf(); + let mut current_indent = 0; + let mut last_item: Option = None; + + for line in layout.lines() { + if let Some((prefix, item)) = line.split_once('-') { + let item = item.replace(std::path::MAIN_SEPARATOR, "_").trim().to_string(); + + let indent = prefix.len() / INDENT_SIZE; + + if last_item.is_none() { + current_indent = indent; + } + + assert!( + indent <= current_indent + 1, + "cannot increase indent by more than {INDENT_SIZE}; item = {item}, current_dir={}", current_dir.display() + ); + + // Go into the last created directory + if indent > current_indent && last_item.is_some() { + let last_item = last_item.unwrap(); + assert!(is_dir(&last_item), "last item was not a dir: {last_item}"); + current_dir.push(last_item); + current_indent += 1; + } + // Go back into an ancestor directory + while indent < current_indent { + current_dir.pop(); + current_indent -= 1; + } + // Create a file or a directory + let item_path = current_dir.join(&item); + if is_dir(&item) { + std::fs::create_dir(&item_path).unwrap_or_else(|e| { + panic!("failed to create dir {}: {e}", item_path.display()) + }); + } else { + std::fs::write(&item_path, "").expect("failed to create file"); + } + + last_item = Some(item); + } + } + } + + // Temporary directory to hold the project. + let tmp = tempfile::tempdir().unwrap(); + // Join a string path to the tmp dir + let path = |p: &str| tmp.path().join(p); + // Check that an expected root is found + let assert_ok = |current_dir: &str, ws: bool, exp: &str| { + let root = find_root(&path(current_dir), ws).expect("should find a root"); + assert_eq!(root, path(exp)); + }; + // Check that a root is not found + let assert_err = |current_dir: &str| { + find_root(&path(current_dir), true).expect_err("shouldn't find a root"); + }; + + let layout = r" + - project + - docs + - workspace + - packages + - foo + - Nargo.toml + - Prover.toml + - src + - main.nr + - bar + - Nargo.toml + - src + - lib.nr + - Nargo.toml + - examples + - baz + - Nargo.toml + - src + - main.nr + "; + + // Set up the file system. + setup(layout, tmp.path()); + + assert_err("dummy"); + assert_err("project/docs"); + assert_err("project/examples"); + assert_ok("project/workspace", true, "project/workspace"); + assert_ok("project/workspace", false, "project/workspace"); + assert_ok("project/workspace/packages/foo", true, "project/workspace"); + assert_ok("project/workspace/packages/bar", false, "project/workspace/packages/bar"); + assert_ok("project/examples/baz/src", true, "project/examples/baz"); + assert_ok("project/examples/baz/src", false, "project/examples/baz"); + } }