Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 22a99c2

Browse files
committedAug 16, 2023
Merge branch 'master' into assert-eq-builtin
* master: chore: update noir-source-resolver from `1.1.2` to `^1.1.3` (#2349) chore(ci): Avoid writing to cache in workflows triggered by the merge queue (#2341) chore(noir): Release 0.10.3 (#2344) feat(lsp): Add `Execute` code lens for `main` functions (#2330) feat(lsp): Add `Compile` code lens for `main` function and contracts (#2309) feat: Allow calling higher-order functions with closures (#2335)
2 parents d7cc198 + 8b99061 commit 22a99c2

File tree

14 files changed

+377
-91
lines changed

14 files changed

+377
-91
lines changed
 

‎.github/workflows/publish.yml

+48-21
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ jobs:
6262
runs-on: macos-latest
6363
env:
6464
CROSS_CONFIG: ${{ github.workspace }}/.github/Cross.toml
65+
CACHED_PATHS: |
66+
~/.cargo/bin/
67+
~/.cargo/registry/index/
68+
~/.cargo/registry/cache/
69+
~/.cargo/git/db/
70+
target/
6571
strategy:
6672
matrix:
6773
target: [x86_64-apple-darwin, aarch64-apple-darwin]
@@ -79,14 +85,10 @@ jobs:
7985
echo "SDKROOT=$(xcrun -sdk macosx$(sw_vers -productVersion) --show-sdk-path)" >> $GITHUB_ENV
8086
echo "MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx$(sw_vers -productVersion) --show-sdk-platform-version)" >> $GITHUB_ENV
8187
82-
- uses: actions/cache@v3
88+
- uses: actions/cache/restore@v3
89+
id: cache
8390
with:
84-
path: |
85-
~/.cargo/bin/
86-
~/.cargo/registry/index/
87-
~/.cargo/registry/cache/
88-
~/.cargo/git/db/
89-
target/
91+
path: ${{ env.CACHED_PATHS }}
9092
key: ${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }}
9193

9294
- name: Download artifact
@@ -106,6 +108,13 @@ jobs:
106108
run: |
107109
cargo build --package nargo_cli --release --target ${{ matrix.target }} --no-default-features --features plonk_bn254_wasm
108110
111+
- uses: actions/cache/save@v3
112+
# Don't create cache entries for the merge queue.
113+
if: ${{ steps.cache.outputs.cache-hit != 'true' && github.event_name != 'merge_group' }}
114+
with:
115+
path: ${{ env.CACHED_PATHS }}
116+
key: ${{ steps.cache.outputs.cache-primary-key }}
117+
109118
- name: Package artifacts
110119
run: |
111120
mkdir dist
@@ -144,6 +153,12 @@ jobs:
144153
runs-on: ubuntu-22.04
145154
env:
146155
CROSS_CONFIG: ${{ github.workspace }}/.github/Cross.toml
156+
CACHED_PATHS: |
157+
~/.cargo/bin/
158+
~/.cargo/registry/index/
159+
~/.cargo/registry/cache/
160+
~/.cargo/git/db/
161+
target/
147162
strategy:
148163
fail-fast: false
149164
matrix:
@@ -161,14 +176,10 @@ jobs:
161176
with:
162177
ref: ${{ inputs.tag || env.GITHUB_REF }}
163178

164-
- uses: actions/cache@v3
179+
- uses: actions/cache/restore@v3
180+
id: cache
165181
with:
166-
path: |
167-
~/.cargo/bin/
168-
~/.cargo/registry/index/
169-
~/.cargo/registry/cache/
170-
~/.cargo/git/db/
171-
target/
182+
path: ${{ env.CACHED_PATHS }}
172183
key: ${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }}
173184

174185
- name: Download artifact
@@ -189,6 +200,13 @@ jobs:
189200
cargo install cross --force --git https://github.com/cross-rs/cross
190201
cross build --package nargo_cli --release --target=${{ matrix.target }} --no-default-features --features plonk_bn254_wasm
191202
203+
- uses: actions/cache/save@v3
204+
# Don't create cache entries for the merge queue.
205+
if: ${{ steps.cache.outputs.cache-hit != 'true' && github.event_name != 'merge_group' }}
206+
with:
207+
path: ${{ env.CACHED_PATHS }}
208+
key: ${{ steps.cache.outputs.cache-primary-key }}
209+
192210
- name: Package artifacts
193211
run: |
194212
mkdir dist
@@ -227,6 +245,12 @@ jobs:
227245
runs-on: windows-2022
228246
env:
229247
CROSS_CONFIG: ${{ github.workspace }}/.github/Cross.toml
248+
CACHED_PATHS: |
249+
~/.cargo/bin/
250+
~/.cargo/registry/index/
251+
~/.cargo/registry/cache/
252+
~/.cargo/git/db/
253+
target/
230254
strategy:
231255
matrix:
232256
target: [x86_64-pc-windows-msvc]
@@ -237,14 +261,10 @@ jobs:
237261
with:
238262
ref: ${{ inputs.tag || env.GITHUB_REF }}
239263

240-
- uses: actions/cache@v3
264+
- uses: actions/cache/restore@v3
265+
id: cache
241266
with:
242-
path: |
243-
~/.cargo/bin/
244-
~/.cargo/registry/index/
245-
~/.cargo/registry/cache/
246-
~/.cargo/git/db/
247-
target/
267+
path: ${{ env.CACHED_PATHS }}
248268
key: ${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }}
249269

250270
- name: Download artifact
@@ -264,6 +284,13 @@ jobs:
264284
run: |
265285
cargo build --package nargo_cli --release --target ${{ matrix.target }} --no-default-features --features plonk_bn254_wasm
266286
287+
- uses: actions/cache/save@v3
288+
# Don't create cache entries for the merge queue.
289+
if: ${{ steps.cache.outputs.cache-hit != 'true' && github.event_name != 'merge_group' }}
290+
with:
291+
path: ${{ env.CACHED_PATHS }}
292+
key: ${{ steps.cache.outputs.cache-primary-key }}
293+
267294
- name: Package artifacts
268295
run: |
269296
mkdir dist

‎.github/workflows/test.yml

+17-8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ jobs:
1414
name: Test on ${{ matrix.os }}
1515
runs-on: ${{ matrix.runner }}
1616
timeout-minutes: 30
17+
env:
18+
CACHED_PATH: /tmp/nix-cache
1719

1820
strategy:
1921
fail-fast: false
@@ -37,27 +39,34 @@ jobs:
3739
name: barretenberg
3840

3941
- name: Restore nix store cache
40-
id: nix-store-cache
41-
uses: actions/cache@v3
42+
uses: actions/cache/restore@v3
43+
id: cache
4244
with:
43-
path: /tmp/nix-cache
45+
path: ${{ env.CACHED_PATH }}
4446
key: ${{ runner.os }}-flake-${{ hashFiles('*.lock') }}
4547

4648
# Based on https://github.com/marigold-dev/deku/blob/b5016f0cf4bf6ac48db9111b70dd7fb49b969dfd/.github/workflows/build.yml#L26
4749
- name: Copy cache into nix store
48-
if: steps.nix-store-cache.outputs.cache-hit == 'true'
50+
if: steps.cache.outputs.cache-hit == 'true'
4951
# We don't check the signature because we're the one that created the cache
5052
run: |
51-
for narinfo in /tmp/nix-cache/*.narinfo; do
53+
for narinfo in ${{ env.CACHED_PATH }}/*.narinfo; do
5254
path=$(head -n 1 "$narinfo" | awk '{print $2}')
53-
nix copy --no-check-sigs --from "file:///tmp/nix-cache" "$path"
55+
nix copy --no-check-sigs --from "file://${{ env.CACHED_PATH }}" "$path"
5456
done
5557
5658
- name: Run `nix flake check`
5759
run: |
5860
nix flake check -L
5961
6062
- name: Export cache from nix store
61-
if: steps.nix-store-cache.outputs.cache-hit != 'true'
63+
if: ${{ always() && steps.cache.outputs.cache-hit != 'true' && github.event_name != 'merge_group' }}
6264
run: |
63-
nix copy --to "file:///tmp/nix-cache?compression=zstd&parallel-compression=true" .#native-cargo-artifacts
65+
nix copy --to "file://${{ env.CACHED_PATH }}?compression=zstd&parallel-compression=true" .#native-cargo-artifacts
66+
67+
- uses: actions/cache/save@v3
68+
# Write a cache entry even if the tests fail but don't create any for the merge queue.
69+
if: ${{ always() && steps.cache.outputs.cache-hit != 'true' && github.event_name != 'merge_group' }}
70+
with:
71+
path: ${{ env.CACHED_PATH }}
72+
key: ${{ steps.cache.outputs.cache-primary-key }}

‎.github/workflows/wasm.yml

+49-7
Original file line numberDiff line numberDiff line change
@@ -49,19 +49,22 @@ jobs:
4949
build-nargo:
5050
needs: [build-barretenberg]
5151
runs-on: ubuntu-22.04
52+
env:
53+
CACHED_PATHS: |
54+
~/.cargo/bin/
55+
~/.cargo/registry/index/
56+
~/.cargo/registry/cache/
57+
~/.cargo/git/db/
58+
target/
5259
5360
steps:
5461
- name: Checkout Noir repo
5562
uses: actions/checkout@v3
5663

57-
- uses: actions/cache@v3
64+
- uses: actions/cache/restore@v3
65+
id: cache
5866
with:
59-
path: |
60-
~/.cargo/bin/
61-
~/.cargo/registry/index/
62-
~/.cargo/registry/cache/
63-
~/.cargo/git/db/
64-
target/
67+
path: ${{ env.CACHED_PATHS }}
6568
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
6669

6770
- name: Download artifact
@@ -79,6 +82,13 @@ jobs:
7982
run: |
8083
cargo build --package nargo_cli --release --no-default-features --features plonk_bn254_wasm
8184
85+
- uses: actions/cache/save@v3
86+
# Don't create cache entries for the merge queue.
87+
if: ${{ steps.cache.outputs.cache-hit != 'true' && github.event_name != 'merge_group' }}
88+
with:
89+
path: ${{ env.CACHED_PATHS }}
90+
key: ${{ steps.cache.outputs.cache-primary-key }}
91+
8292
- name: Package artifacts
8393
run: |
8494
mkdir dist
@@ -94,6 +104,9 @@ jobs:
94104

95105
build-wasm:
96106
runs-on: ubuntu-latest
107+
env:
108+
CACHED_PATH: /tmp/nix-cache
109+
97110
steps:
98111
- name: Checkout sources
99112
uses: actions/checkout@v3
@@ -104,10 +117,39 @@ jobs:
104117
nix_path: nixpkgs=channel:nixos-22.11
105118
github_access_token: ${{ secrets.GITHUB_TOKEN }}
106119

120+
- name: Restore nix store cache
121+
uses: actions/cache/restore@v3
122+
id: cache
123+
with:
124+
path: ${{ env.CACHED_PATH }}
125+
key: ${{ runner.os }}-flake-wasm-${{ hashFiles('*.lock') }}
126+
127+
# Based on https://github.com/marigold-dev/deku/blob/b5016f0cf4bf6ac48db9111b70dd7fb49b969dfd/.github/workflows/build.yml#L26
128+
- name: Copy cache into nix store
129+
if: steps.cache.outputs.cache-hit == 'true'
130+
# We don't check the signature because we're the one that created the cache
131+
run: |
132+
for narinfo in ${{ env.CACHED_PATH }}/*.narinfo; do
133+
path=$(head -n 1 "$narinfo" | awk '{print $2}')
134+
nix copy --no-check-sigs --from "file://${{ env.CACHED_PATH }}" "$path"
135+
done
136+
107137
- name: Build wasm package
108138
run: |
109139
nix build -L .#wasm
110140
141+
- name: Export cache from nix store
142+
if: ${{ steps.cache.outputs.cache-hit != 'true' && github.event_name != 'merge_group' }}
143+
run: |
144+
nix copy --to "file://${{ env.CACHED_PATH }}?compression=zstd&parallel-compression=true" .#noir-wasm-cargo-artifacts
145+
146+
- uses: actions/cache/save@v3
147+
# Don't create cache entries for the merge queue.
148+
if: ${{ steps.cache.outputs.cache-hit != 'true' && github.event_name != 'merge_group' }}
149+
with:
150+
path: ${{ env.CACHED_PATH }}
151+
key: ${{ steps.cache.outputs.cache-primary-key }}
152+
111153
- name: Dereference symlink
112154
run: echo "UPLOAD_PATH=$(readlink -f result)" >> $GITHUB_ENV
113155

‎.release-please-manifest.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "0.10.2"
2+
".": "0.10.3"
33
}

‎CHANGELOG.md

+14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Changelog
22

3+
## [0.10.3](https://github.com/noir-lang/noir/compare/v0.10.2...v0.10.3) (2023-08-16)
4+
5+
6+
### Features
7+
8+
* Allow calling higher-order functions with closures ([#2335](https://github.com/noir-lang/noir/issues/2335)) ([75fd3e0](https://github.com/noir-lang/noir/commit/75fd3e0e27f16fb0aa5f8b01cefe78e04f867726))
9+
* **lsp:** Add `Compile` code lens for `main` function and contracts ([#2309](https://github.com/noir-lang/noir/issues/2309)) ([5fe69c6](https://github.com/noir-lang/noir/commit/5fe69c6eeef0b7ed2e4df9c3a80627f54c75a355))
10+
* **lsp:** Add `Execute` code lens for `main` functions ([#2330](https://github.com/noir-lang/noir/issues/2330)) ([5aa59e0](https://github.com/noir-lang/noir/commit/5aa59e0f3c4b3e6e14330d1f0e45ec912f562892))
11+
12+
13+
### Bug Fixes
14+
15+
* Display warning if last expression of block is unused ([#2314](https://github.com/noir-lang/noir/issues/2314)) ([8110136](https://github.com/noir-lang/noir/commit/81101362ccba787a44c6d48c0378696cb16f0acb))
16+
317
## [0.10.2](https://github.com/noir-lang/noir/compare/v0.10.1...v0.10.2) (2023-08-16)
418

519

‎Cargo.lock

+13-13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ default-members = ["crates/nargo_cli"]
1818

1919
[workspace.package]
2020
# x-release-please-start-version
21-
version = "0.10.2"
21+
version = "0.10.3"
2222
# x-release-please-end
2323
authors = ["The Noir Team <team@noir-lang.org>"]
2424
edition = "2021"

‎crates/lsp/src/lib.rs

+163-6
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@ use noirc_frontend::hir::FunctionNameMatch;
2727
use serde_json::Value as JsonValue;
2828
use tower::Service;
2929

30+
const ARROW: &str = "▶\u{fe0e}";
3031
const TEST_COMMAND: &str = "nargo.test";
31-
const TEST_CODELENS_TITLE: &str = "▶\u{fe0e} Run Test";
32+
const TEST_CODELENS_TITLE: &str = "Run Test";
33+
const COMPILE_COMMAND: &str = "nargo.compile";
34+
const COMPILE_CODELENS_TITLE: &str = "Compile";
35+
const EXECUTE_COMMAND: &str = "nargo.execute";
36+
const EXECUTE_CODELENS_TITLE: &str = "Execute";
3237

3338
// State for the LSP gets implemented on this struct and is internal to the implementation
3439
pub struct LspState {
@@ -185,7 +190,7 @@ fn on_code_lens_request(
185190

186191
for package in &workspace {
187192
let (mut context, crate_id) = prepare_package(package);
188-
// We ignore the warnings and errors produced by compilation for producing codelenses
193+
// We ignore the warnings and errors produced by compilation for producing code lenses
189194
// because we can still get the test functions even if compilation fails
190195
let _ = check_crate(&mut context, crate_id, false);
191196

@@ -209,8 +214,8 @@ fn on_code_lens_request(
209214
let range = byte_span_to_range(files, file_id.as_usize(), location.span.into())
210215
.unwrap_or_default();
211216

212-
let command = Command {
213-
title: TEST_CODELENS_TITLE.into(),
217+
let test_command = Command {
218+
title: format!("{ARROW} {TEST_CODELENS_TITLE}"),
214219
command: TEST_COMMAND.into(),
215220
arguments: Some(vec![
216221
"--program-dir".into(),
@@ -222,9 +227,158 @@ fn on_code_lens_request(
222227
]),
223228
};
224229

225-
let lens = CodeLens { range, command: command.into(), data: None };
230+
let test_lens = CodeLens { range, command: Some(test_command), data: None };
226231

227-
lenses.push(lens);
232+
lenses.push(test_lens);
233+
}
234+
235+
if package.is_binary() {
236+
if let Some(main_func_id) = context.get_main_function(&crate_id) {
237+
let location = context.function_meta(&main_func_id).name.location;
238+
let file_id = location.file;
239+
240+
// Ignore diagnostics for any file that wasn't the file we saved
241+
// TODO: In the future, we could create "related" diagnostics for these files
242+
// TODO: This currently just appends the `.nr` file extension that we store as a constant,
243+
// but that won't work if we accept other extensions
244+
if fm.path(file_id).with_extension(FILE_EXTENSION) != file_path {
245+
continue;
246+
}
247+
248+
let range = byte_span_to_range(files, file_id.as_usize(), location.span.into())
249+
.unwrap_or_default();
250+
251+
let compile_command = Command {
252+
title: format!("{ARROW} {COMPILE_CODELENS_TITLE}"),
253+
command: COMPILE_COMMAND.into(),
254+
arguments: Some(vec![
255+
"--program-dir".into(),
256+
format!("{}", workspace.root_dir.display()).into(),
257+
"--package".into(),
258+
format!("{}", package.name).into(),
259+
]),
260+
};
261+
262+
let compile_lens = CodeLens { range, command: Some(compile_command), data: None };
263+
264+
lenses.push(compile_lens);
265+
266+
let execute_command = Command {
267+
title: EXECUTE_CODELENS_TITLE.to_string(),
268+
command: EXECUTE_COMMAND.into(),
269+
arguments: Some(vec![
270+
"--program-dir".into(),
271+
format!("{}", workspace.root_dir.display()).into(),
272+
"--package".into(),
273+
format!("{}", package.name).into(),
274+
]),
275+
};
276+
277+
let execute_lens = CodeLens { range, command: Some(execute_command), data: None };
278+
279+
lenses.push(execute_lens);
280+
}
281+
}
282+
283+
if package.is_contract() {
284+
// Currently not looking to deduplicate this since we don't have a clear decision on if the Contract stuff is staying
285+
for contract in context.get_all_contracts(&crate_id) {
286+
let location = contract.location;
287+
let file_id = location.file;
288+
289+
// Ignore diagnostics for any file that wasn't the file we saved
290+
// TODO: In the future, we could create "related" diagnostics for these files
291+
// TODO: This currently just appends the `.nr` file extension that we store as a constant,
292+
// but that won't work if we accept other extensions
293+
if fm.path(file_id).with_extension(FILE_EXTENSION) != file_path {
294+
continue;
295+
}
296+
297+
let range = byte_span_to_range(files, file_id.as_usize(), location.span.into())
298+
.unwrap_or_default();
299+
300+
let compile_command = Command {
301+
title: format!("{ARROW} {COMPILE_CODELENS_TITLE}"),
302+
command: COMPILE_COMMAND.into(),
303+
arguments: Some(vec![
304+
"--program-dir".into(),
305+
format!("{}", workspace.root_dir.display()).into(),
306+
"--package".into(),
307+
format!("{}", package.name).into(),
308+
]),
309+
};
310+
311+
let compile_lens = CodeLens { range, command: Some(compile_command), data: None };
312+
313+
lenses.push(compile_lens);
314+
}
315+
}
316+
317+
if package.is_binary() {
318+
if let Some(main_func_id) = context.get_main_function(&crate_id) {
319+
let location = context.function_meta(&main_func_id).name.location;
320+
let file_id = location.file;
321+
322+
// Ignore diagnostics for any file that wasn't the file we saved
323+
// TODO: In the future, we could create "related" diagnostics for these files
324+
// TODO: This currently just appends the `.nr` file extension that we store as a constant,
325+
// but that won't work if we accept other extensions
326+
if fm.path(file_id).with_extension(FILE_EXTENSION) != file_path {
327+
continue;
328+
}
329+
330+
let range = byte_span_to_range(files, file_id.as_usize(), location.span.into())
331+
.unwrap_or_default();
332+
333+
let command = Command {
334+
title: format!("{ARROW} {COMPILE_CODELENS_TITLE}"),
335+
command: COMPILE_COMMAND.into(),
336+
arguments: Some(vec![
337+
"--program-dir".into(),
338+
format!("{}", workspace.root_dir.display()).into(),
339+
"--package".into(),
340+
format!("{}", package.name).into(),
341+
]),
342+
};
343+
344+
let lens = CodeLens { range, command: command.into(), data: None };
345+
346+
lenses.push(lens);
347+
}
348+
}
349+
350+
if package.is_contract() {
351+
// Currently not looking to deduplicate this since we don't have a clear decision on if the Contract stuff is staying
352+
for contract in context.get_all_contracts(&crate_id) {
353+
let location = contract.location;
354+
let file_id = location.file;
355+
356+
// Ignore diagnostics for any file that wasn't the file we saved
357+
// TODO: In the future, we could create "related" diagnostics for these files
358+
// TODO: This currently just appends the `.nr` file extension that we store as a constant,
359+
// but that won't work if we accept other extensions
360+
if fm.path(file_id).with_extension(FILE_EXTENSION) != file_path {
361+
continue;
362+
}
363+
364+
let range = byte_span_to_range(files, file_id.as_usize(), location.span.into())
365+
.unwrap_or_default();
366+
367+
let command = Command {
368+
title: format!("{ARROW} {COMPILE_CODELENS_TITLE}"),
369+
command: COMPILE_COMMAND.into(),
370+
arguments: Some(vec![
371+
"--program-dir".into(),
372+
format!("{}", workspace.root_dir.display()).into(),
373+
"--package".into(),
374+
format!("{}", package.name).into(),
375+
]),
376+
};
377+
378+
let lens = CodeLens { range, command: command.into(), data: None };
379+
380+
lenses.push(lens);
381+
}
228382
}
229383
}
230384

@@ -365,6 +519,9 @@ fn on_did_save_text_document(
365519
}
366520
}
367521

522+
// We need to refresh lenses when we compile since that's the only time they can be accurately reflected
523+
let _ = state.client.code_lens_refresh(());
524+
368525
let _ = state.client.publish_diagnostics(PublishDiagnosticsParams {
369526
uri: params.text_document.uri,
370527
version: None,

‎crates/noirc_frontend/src/hir/def_map/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl CrateDefMap {
148148
let functions =
149149
module.value_definitions().filter_map(|id| id.as_function()).collect();
150150
let name = self.get_module_path(id, module.parent);
151-
Some(Contract { name, functions })
151+
Some(Contract { name, location: module.location, functions })
152152
} else {
153153
None
154154
}
@@ -194,6 +194,7 @@ impl CrateDefMap {
194194
pub struct Contract {
195195
/// To keep `name` semi-unique, it is prefixed with the names of parent modules via CrateDefMap::get_module_path
196196
pub name: String,
197+
pub location: Location,
197198
pub functions: Vec<FuncId>,
198199
}
199200

‎crates/noirc_frontend/src/hir/type_check/expr.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -837,11 +837,13 @@ impl<'interner> TypeChecker<'interner> {
837837
}
838838

839839
for (param, (arg, _, arg_span)) in fn_params.iter().zip(callsite_args) {
840-
self.unify(arg, param, || TypeCheckError::TypeMismatch {
841-
expected_typ: param.to_string(),
842-
expr_typ: arg.to_string(),
843-
expr_span: *arg_span,
844-
});
840+
if arg.try_unify_allow_incompat_lambdas(param).is_err() {
841+
self.errors.push(TypeCheckError::TypeMismatch {
842+
expected_typ: param.to_string(),
843+
expr_typ: arg.to_string(),
844+
expr_span: *arg_span,
845+
});
846+
}
845847
}
846848

847849
fn_ret.clone()

‎crates/noirc_frontend/src/hir/type_check/mod.rs

+25-20
Original file line numberDiff line numberDiff line change
@@ -63,28 +63,33 @@ pub fn type_check_func(interner: &mut NodeInterner, func_id: FuncId) -> Vec<Type
6363
let (expr_span, empty_function) = function_info(interner, function_body_id);
6464

6565
let func_span = interner.expr_span(function_body_id); // XXX: We could be more specific and return the span of the last stmt, however stmts do not have spans yet
66-
function_last_type.unify_with_coercions(
67-
&declared_return_type,
68-
*function_body_id,
69-
interner,
70-
&mut errors,
71-
|| {
72-
let mut error = TypeCheckError::TypeMismatchWithSource {
73-
lhs: declared_return_type.clone(),
74-
rhs: function_last_type.clone(),
75-
span: func_span,
76-
source: Source::Return(meta.return_type, expr_span),
77-
};
7866

79-
if empty_function {
80-
error = error.add_context(
81-
"implicitly returns `()` as its body has no tail or `return` expression",
82-
);
83-
}
67+
let result = function_last_type.try_unify_allow_incompat_lambdas(&declared_return_type);
68+
69+
if result.is_err() {
70+
function_last_type.unify_with_coercions(
71+
&declared_return_type,
72+
*function_body_id,
73+
interner,
74+
&mut errors,
75+
|| {
76+
let mut error = TypeCheckError::TypeMismatchWithSource {
77+
lhs: declared_return_type.clone(),
78+
rhs: function_last_type.clone(),
79+
span: func_span,
80+
source: Source::Return(meta.return_type, expr_span),
81+
};
82+
83+
if empty_function {
84+
error = error.add_context(
85+
"implicitly returns `()` as its body has no tail or `return` expression",
86+
);
87+
}
8488

85-
error
86-
},
87-
);
89+
error
90+
},
91+
);
92+
}
8893
}
8994

9095
errors

‎crates/noirc_frontend/src/hir_def/types.rs

+32-4
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ pub enum Type {
5454
/// TypeVariables are stand-in variables for some type which is not yet known.
5555
/// They are not to be confused with NamedGenerics. While the later mostly works
5656
/// as with normal types (ie. for two NamedGenerics T and U, T != U), TypeVariables
57-
/// will be automatically rebound as necessary to satisfy any calls to unify
58-
/// and make_subtype_of.
57+
/// will be automatically rebound as necessary to satisfy any calls to unify.
5958
///
6059
/// TypeVariables are often created when a generic function is instantiated. This
6160
/// is a process that replaces each NamedGeneric in a generic function with a TypeVariable.
@@ -885,7 +884,36 @@ impl Type {
885884
}
886885
}
887886

888-
/// Similar to `make_subtype_of` but if the check fails this will attempt to coerce the
887+
/// Similar to try_unify() but allows non-matching capture groups for function types
888+
pub fn try_unify_allow_incompat_lambdas(&self, other: &Type) -> Result<(), UnificationError> {
889+
use Type::*;
890+
use TypeVariableKind::*;
891+
892+
match (self, other) {
893+
(TypeVariable(binding, Normal), other) | (other, TypeVariable(binding, Normal)) => {
894+
if let TypeBinding::Bound(link) = &*binding.borrow() {
895+
return link.try_unify_allow_incompat_lambdas(other);
896+
}
897+
898+
other.try_bind_to(binding)
899+
}
900+
(Function(params_a, ret_a, _), Function(params_b, ret_b, _)) => {
901+
if params_a.len() == params_b.len() {
902+
for (a, b) in params_a.iter().zip(params_b.iter()) {
903+
a.try_unify_allow_incompat_lambdas(b)?;
904+
}
905+
906+
// no check for environments here!
907+
ret_b.try_unify_allow_incompat_lambdas(ret_a)
908+
} else {
909+
Err(UnificationError)
910+
}
911+
}
912+
_ => self.try_unify(other),
913+
}
914+
}
915+
916+
/// Similar to `unify` but if the check fails this will attempt to coerce the
889917
/// argument to the target type. When this happens, the given expression is wrapped in
890918
/// a new expression to convert its type. E.g. `array` -> `array.as_slice()`
891919
///
@@ -923,7 +951,7 @@ impl Type {
923951
// If we have an array and our target is a slice
924952
if matches!(size1, Type::Constant(_)) && matches!(size2, Type::NotConstant) {
925953
// Still have to ensure the element types match.
926-
// Don't need to issue an error here if not, it will be done in make_subtype_of_with_coercions
954+
// Don't need to issue an error here if not, it will be done in unify_with_coercions
927955
if element1.try_unify(element2).is_ok() {
928956
convert_array_expression_to_slice(expression, this, target, interner);
929957
return true;

‎crates/wasm/package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"collaborators": [
44
"The Noir Team <team@noir-lang.org>"
55
],
6-
"version": "0.10.2",
6+
"version": "0.10.3",
77
"license": "(MIT OR Apache-2.0)",
88
"main": "./nodejs/noir_wasm.js",
99
"types": "./web/noir_wasm.d.ts",
@@ -24,11 +24,11 @@
2424
"test:browser": "web-test-runner"
2525
},
2626
"peerDependencies": {
27-
"@noir-lang/noir-source-resolver": "1.1.2"
27+
"@noir-lang/noir-source-resolver": "^1.1.3"
2828
},
2929
"devDependencies": {
3030
"@esm-bundle/chai": "^4.3.4-fix.0",
31-
"@noir-lang/noir-source-resolver": "1.1.2",
31+
"@noir-lang/noir-source-resolver": "^1.1.3",
3232
"@web/dev-server-esbuild": "^0.3.6",
3333
"@web/test-runner": "^0.15.3",
3434
"@web/test-runner-playwright": "^0.10.0",

‎flake.nix

+2-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117

118118
sharedArgs = {
119119
# x-release-please-start-version
120-
version = "0.10.2";
120+
version = "0.10.3";
121121
# x-release-please-end
122122

123123
src = pkgs.lib.cleanSourceWith {
@@ -254,6 +254,7 @@
254254
# We expose the `*-cargo-artifacts` derivations so we can cache our cargo dependencies in CI
255255
inherit native-cargo-artifacts;
256256
inherit wasm-cargo-artifacts;
257+
inherit noir-wasm-cargo-artifacts;
257258
};
258259

259260
# TODO(#1197): Look into installable apps with Nix flakes

0 commit comments

Comments
 (0)
Please sign in to comment.