Skip to content

Commit

Permalink
feat: add Type::implements (#5701)
Browse files Browse the repository at this point in the history
# Description

## Problem

Part of #5668

## Summary



## Additional Context



## Documentation

Check one:
- [x] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[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 9, 2024
1 parent e4f7dbe commit 2166c94
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 0 deletions.
16 changes: 16 additions & 0 deletions compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ impl<'local, 'context> Interpreter<'local, 'context> {
"type_as_struct" => type_as_struct(arguments, return_type, location),
"type_as_tuple" => type_as_tuple(arguments, return_type, location),
"type_eq" => type_eq(arguments, location),
"type_implements" => type_implements(interner, arguments, location),
"type_is_bool" => type_is_bool(arguments, location),
"type_is_field" => type_is_field(arguments, location),
"type_of" => type_of(arguments, location),
Expand Down Expand Up @@ -490,6 +491,21 @@ fn type_eq(arguments: Vec<(Value, Location)>, location: Location) -> IResult<Val
Ok(Value::Bool(self_type == other_type))
}

// fn implements(self, constraint: TraitConstraint) -> bool
fn type_implements(
interner: &NodeInterner,
arguments: Vec<(Value, Location)>,
location: Location,
) -> IResult<Value> {
let (typ, constraint) = check_two_arguments(arguments, location)?;

let typ = get_type(typ)?;
let (trait_id, generics) = get_trait_constraint(constraint)?;

let implements = interner.try_lookup_trait_implementation(&typ, trait_id, &generics).is_ok();
Ok(Value::Bool(implements))
}

// fn is_bool(self) -> bool
fn type_is_bool(arguments: Vec<(Value, Location)>, location: Location) -> IResult<Value> {
let value = check_one_argument(arguments, location)?;
Expand Down
3 changes: 3 additions & 0 deletions noir_stdlib/src/meta/typ.nr
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ impl Type {
#[builtin(type_as_tuple)]
fn as_tuple(self) -> Option<[Type]> {}

#[builtin(type_implements)]
fn implements(self, constraint: TraitConstraint) -> bool {}

#[builtin(type_is_bool)]
fn is_bool(self) -> bool {}

Expand Down
35 changes: 35 additions & 0 deletions test_programs/compile_success_empty/comptime_type/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@ struct Foo<T> {
x: T
}

trait SomeTrait<T> {

}
struct StructImplementsSomeTrait {

}

impl SomeTrait<i32> for StructImplementsSomeTrait {

}

struct StructDoesNotImplementSomeTrait {

}

fn main() {
comptime
{
Expand Down Expand Up @@ -82,5 +97,25 @@ fn main() {

assert_eq(generics.len(), 1);
assert_eq(generics[0], field_type_1);

// Check Type::implements
let some_trait_i32 = quote { SomeTrait<i32> }.as_trait_constraint();
let struct_implements_some_trait = quote { StructImplementsSomeTrait }.as_type();
let struct_does_not_implement_some_trait = quote { StructDoesNotImplementSomeTrait }.as_type();
assert(struct_implements_some_trait.implements(some_trait_i32));
assert(!struct_does_not_implement_some_trait.implements(some_trait_i32));

let some_trait_field = quote { SomeTrait<Field> }.as_trait_constraint();
assert(!struct_implements_some_trait.implements(some_trait_field));
assert(!struct_does_not_implement_some_trait.implements(some_trait_field));
}
}

fn function_with_where<T>(_x: T) where T: SomeTrait<i32> {
comptime
{
let t = quote { T }.as_type();
let some_trait_i32 = quote { SomeTrait<i32> }.as_trait_constraint();
assert(t.implements(some_trait_i32));
}
}

0 comments on commit 2166c94

Please sign in to comment.