diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs index 017ea360562..771f23335fd 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -5,12 +5,14 @@ use std::{ use acvm::{AcirField, FieldElement}; use chumsky::Parser; +use iter_extended::vecmap; use noirc_errors::Location; use crate::{ ast::{IntegerBitSize, TraitBound}, hir::comptime::{errors::IResult, InterpreterError, Value}, - macros_api::{NodeInterner, Signedness}, + macros_api::{NodeInterner, Path, Signedness, UnresolvedTypeData}, + node_interner::TraitId, parser, token::{SpannedToken, Token, Tokens}, QuotedType, Type, @@ -42,6 +44,9 @@ pub(super) fn call_builtin( "struct_def_generics" => struct_def_generics(interner, arguments, location), "trait_constraint_eq" => trait_constraint_eq(interner, arguments, location), "trait_constraint_hash" => trait_constraint_hash(interner, arguments, location), + "trait_def_as_trait_constraint" => { + trait_def_as_trait_constraint(interner, arguments, location) + } "quoted_as_trait_constraint" => quoted_as_trait_constraint(interner, arguments, location), _ => { let item = format!("Comptime evaluation for builtin function {name}"); @@ -103,6 +108,16 @@ fn get_trait_constraint(value: Value, location: Location) -> IResult } } +fn get_trait_def(value: Value, location: Location) -> IResult { + match value { + Value::TraitDefinition(id) => Ok(id), + value => { + let expected = Type::Quoted(QuotedType::TraitDefinition); + Err(InterpreterError::TypeMismatch { expected, value, location }) + } + } +} + fn get_quoted(value: Value, location: Location) -> IResult> { match value { Value::Code(tokens) => Ok(tokens), @@ -456,3 +471,24 @@ fn modulus_num_bits( let bits = FieldElement::max_num_bits().into(); Ok(Value::U64(bits)) } + +fn trait_def_as_trait_constraint( + interner: &mut NodeInterner, + mut arguments: Vec<(Value, Location)>, + location: Location, +) -> Result { + check_argument_count(1, &arguments, location)?; + + let trait_id = get_trait_def(arguments.pop().unwrap().0, location)?; + let the_trait = interner.get_trait(trait_id); + + let trait_path = Path::from_ident(the_trait.name.clone()); + + let trait_generics = vecmap(&the_trait.generics, |generic| { + let name = Path::from_single(generic.name.as_ref().clone(), generic.span); + UnresolvedTypeData::Named(name, Vec::new(), false).with_span(generic.span) + }); + + let trait_id = Some(trait_id); + Ok(Value::TraitConstraint(TraitBound { trait_path, trait_id, trait_generics })) +} diff --git a/noir_stdlib/src/meta/mod.nr b/noir_stdlib/src/meta/mod.nr index ed3365d755c..395f09a453e 100644 --- a/noir_stdlib/src/meta/mod.nr +++ b/noir_stdlib/src/meta/mod.nr @@ -1,5 +1,6 @@ -mod type_def; mod trait_constraint; +mod trait_def; +mod type_def; mod quoted; /// Calling unquote as a macro (via `unquote!(arg)`) will unquote diff --git a/noir_stdlib/src/meta/trait_def.nr b/noir_stdlib/src/meta/trait_def.nr new file mode 100644 index 00000000000..5de7631e34d --- /dev/null +++ b/noir_stdlib/src/meta/trait_def.nr @@ -0,0 +1,4 @@ +impl TraitDefinition { + #[builtin(trait_def_as_trait_constraint)] + fn as_trait_constraint(_self: Self) -> TraitConstraint {} +} diff --git a/test_programs/compile_success_empty/trait_as_constraint/Nargo.toml b/test_programs/compile_success_empty/trait_as_constraint/Nargo.toml new file mode 100644 index 00000000000..907b5ce09ed --- /dev/null +++ b/test_programs/compile_success_empty/trait_as_constraint/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "trait_as_constraint" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/trait_as_constraint/src/main.nr b/test_programs/compile_success_empty/trait_as_constraint/src/main.nr new file mode 100644 index 00000000000..1911f045c27 --- /dev/null +++ b/test_programs/compile_success_empty/trait_as_constraint/src/main.nr @@ -0,0 +1,9 @@ +#[test_as_constraint] +trait Foo {} + +comptime fn test_as_constraint(t: TraitDefinition) { + let constraint = t.as_trait_constraint(); + assert(constraint == constraint); +} + +fn main() {}