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: add support for wildcard types #5275

Merged
merged 6 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion compiler/noirc_frontend/src/elaborator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
def_map::ModuleDefId,
resolution::{
errors::ResolverError,
resolver::{verify_mutable_reference, SELF_TYPE_NAME},
resolver::{verify_mutable_reference, SELF_TYPE_NAME, WILDCARD_TYPE},
},
type_check::{Source, TypeCheckError},
},
Expand Down Expand Up @@ -146,6 +146,8 @@ impl<'context> Elaborator<'context> {
}
return self_type;
}
} else if name == WILDCARD_TYPE {
return self.interner.next_type_variable();
}
}

Expand Down
1 change: 1 addition & 0 deletions compiler/noirc_frontend/src/hir/resolution/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ use super::errors::{PubPosition, ResolverError};
use super::import::PathResolution;

pub const SELF_TYPE_NAME: &str = "Self";
pub const WILDCARD_TYPE: &str = "_";

type Scope = GenericScope<String, ResolverMeta>;
type ScopeTree = GenericScopeTree<String, ResolverMeta>;
Expand Down
8 changes: 8 additions & 0 deletions docs/docs/noir/concepts/data_types/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ type Bad2 = Bad1;
// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2
```

## Wildcard Type
Noir can usually infer the type of the variable from the context, so specifying the type of a variable is only required when it cannot be inferred. However, specifying a complex type can be tedious, especially when it has multiple generic arguments. Often some of the generic types can be inferred from the context, and Noir only needs a hint to properly infer the other types. We can partially specify a variable's type by using `_` as a marker, indicating where we still want the compiler to infer the type.

```rust
let a: [_; 4] = foo(b);
```


### BigInt

You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library.
6 changes: 6 additions & 0 deletions test_programs/execution_success/wildcard_type/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "wildcard_type"
type = "bin"
authors = [""]

[dependencies]
1 change: 1 addition & 0 deletions test_programs/execution_success/wildcard_type/Prover.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
enable = [4,7]
23 changes: 23 additions & 0 deletions test_programs/execution_success/wildcard_type/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
struct bar {
enable: [bool; 4],
data: [Field; 2],
pad: u32,
}

fn main(enable: [Field; 2]) -> pub [Field; 4] {
let mut result = [0; 4];
let a: [_; 4] = foo(enable[1]);
for i in 0..4 {
result[i] = a[i].data[i % 2];
}
result
}

fn foo(x: Field) -> [bar; 4] {
[
bar { enable: [true, true, false, false], data: [x, x + 1], pad: 0 },
bar { enable: [true, false, false, false], data: [x + 2, x + 7], pad: 0 },
bar { enable: [true, true, false, true], data: [x + 3, x + 5], pad: 0 },
bar { enable: [false, false, false, false], data: [x + 4, x - 1], pad: 0 }
]
}
18 changes: 13 additions & 5 deletions tooling/nargo_cli/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ const IGNORED_BRILLIG_TESTS: [&str; 11] = [
"is_unconstrained",
];

/// Certain comptime features are only available in the elaborator.
/// Certain features are only available in the elaborator.
/// We skip these tests for non-elaborator code since they are not
/// expected to work there. This can be removed once the old code is removed.
const IGNORED_COMPTIME_TESTS: [&str; 1] = ["macros"];
const IGNORED_NEW_FEATURE_TESTS: [&str; 2] = ["macros", "wildcard_type"];

fn generate_execution_success_tests(test_file: &mut File, test_data_dir: &Path) {
let test_sub_dir = "execution_success";
Expand All @@ -82,11 +82,16 @@ fn generate_execution_success_tests(test_file: &mut File, test_data_dir: &Path)

let brillig_ignored =
if IGNORED_BRILLIG_TESTS.contains(&test_name.as_str()) { "\n#[ignore]" } else { "" };
let new_features_ignored = if IGNORED_NEW_FEATURE_TESTS.contains(&test_name.as_str()) {
"\n#[ignore]"
} else {
""
};

write!(
test_file,
r#"
#[test]
#[test]{new_features_ignored}
fn execution_success_legacy_{test_name}() {{
let test_program_dir = PathBuf::from("{test_dir}");

Expand Down Expand Up @@ -286,8 +291,11 @@ fn generate_compile_success_empty_tests(test_file: &mut File, test_data_dir: &Pa
};
let test_dir = &test_dir.path();

let comptime_ignored =
if IGNORED_COMPTIME_TESTS.contains(&test_name.as_str()) { "\n#[ignore]" } else { "" };
let comptime_ignored = if IGNORED_NEW_FEATURE_TESTS.contains(&test_name.as_str()) {
"\n#[ignore]"
} else {
""
};

write!(
test_file,
Expand Down
Loading