Skip to content

Commit

Permalink
feat: add std::meta::type_of and impl Eq for Type (#5669)
Browse files Browse the repository at this point in the history
# Description

## Problem

Part of #5668

## Summary

I originally wanted to just add `type_of`, but in order to test it in
some way I thought of comparing two types and checking whether they are
equal or not... which required implementing `Eq` for `Type`, which I
guess is useful any way.

## Additional Context

Another way could have been to be able to turn a `Type` into a string
and check that, but there's no unbounded `String` type at comptime...
Another way would be to `println` the type and check the program's
output, but there's no quick way to do it right now... but I think
asserting on equality is fine too, especially because the implementation
of `type_of` is very simple.

## Documentation\*

Check one:
- [ ] No documentation needed.
- [ ] Documentation included in this PR.
- [x] **[For Experimental Features]** Documentation to be submitted in a
separate PR.

# PR Checklist\*

- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
  • Loading branch information
asterite authored Aug 1, 2024
1 parent e5f1b36 commit 0503956
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 0 deletions.
18 changes: 18 additions & 0 deletions compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ impl<'local, 'context> Interpreter<'local, 'context> {
}
"quoted_as_trait_constraint" => quoted_as_trait_constraint(self, arguments, location),
"quoted_as_type" => quoted_as_type(self, arguments, location),
"type_eq" => type_eq(arguments, location),
"type_of" => type_of(arguments, location),
"zeroed" => zeroed(return_type),
_ => {
let item = format!("Comptime evaluation for builtin function {name}");
Expand Down Expand Up @@ -434,6 +436,22 @@ fn quoted_as_type(
Ok(Value::Type(typ))
}

fn type_eq(mut arguments: Vec<(Value, Location)>, location: Location) -> IResult<Value> {
check_argument_count(2, &arguments, location)?;

let value1 = arguments.pop().unwrap().0;
let value2 = arguments.pop().unwrap().0;
Ok(Value::Bool(value1 == value2))
}

fn type_of(mut arguments: Vec<(Value, Location)>, location: Location) -> IResult<Value> {
check_argument_count(1, &arguments, location)?;

let value = arguments.pop().unwrap().0;
let typ = value.get_type().into_owned();
Ok(Value::Type(typ))
}

// fn constraint_hash(constraint: TraitConstraint) -> Field
fn trait_constraint_hash(
_interner: &mut NodeInterner,
Expand Down
5 changes: 5 additions & 0 deletions noir_stdlib/src/meta/mod.nr
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod trait_constraint;
mod trait_def;
mod typ;
mod type_def;
mod quoted;

Expand All @@ -9,3 +10,7 @@ mod quoted;
pub comptime fn unquote(code: Quoted) -> Quoted {
code
}

#[builtin(type_of)]
pub comptime fn type_of<T>(x: T) -> Type {}

10 changes: 10 additions & 0 deletions noir_stdlib/src/meta/typ.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use crate::cmp::Eq;

impl Eq for Type {
fn eq(self, other: Self) -> bool {
type_eq(self, other)
}
}

#[builtin(type_eq)]
fn type_eq(_first: Type, _second: Type) -> bool {}
7 changes: 7 additions & 0 deletions test_programs/compile_success_empty/comptime_type/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "comptime_type"
type = "bin"
authors = [""]
compiler_version = ">=0.31.0"

[dependencies]
16 changes: 16 additions & 0 deletions test_programs/compile_success_empty/comptime_type/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use std::meta::type_of;

fn main() {
comptime
{
// Check type_of works correctly (relies on Eq for Type)
let a_field = 0;
let another_field = 1;
let an_i32: i32 = 0;
let field_type_1 = type_of(a_field);
let field_type_2 = type_of(another_field);
let i32_type = type_of(an_i32);
assert(field_type_1 == field_type_2);
assert(field_type_1 != i32_type);
}
}

0 comments on commit 0503956

Please sign in to comment.