diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs index ebdbddb1c41..4fb747b74c6 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -61,6 +61,7 @@ impl<'local, 'context> Interpreter<'local, 'context> { "type_as_constant" => type_as_constant(arguments, return_type, location), "type_as_integer" => type_as_integer(arguments, return_type, location), "type_as_slice" => type_as_slice(arguments, return_type, location), + "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_is_bool" => type_is_bool(arguments, location), @@ -550,6 +551,27 @@ fn type_as_slice( }) } +// fn as_struct(self) -> Option<(StructDefinition, [Type])> +fn type_as_struct( + arguments: Vec<(Value, Location)>, + return_type: Type, + location: Location, +) -> IResult { + type_as(arguments, return_type, location, |typ| { + if let Type::Struct(struct_type, generics) = typ { + Some(Value::Tuple(vec![ + Value::StructDefinition(struct_type.borrow().id), + Value::Slice( + generics.into_iter().map(Value::Type).collect(), + Type::Slice(Box::new(Type::Quoted(QuotedType::Type))), + ), + ])) + } else { + None + } + }) +} + // fn as_tuple(self) -> Option<[Type]> fn type_as_tuple( arguments: Vec<(Value, Location)>, diff --git a/noir_stdlib/src/meta/typ.nr b/noir_stdlib/src/meta/typ.nr index 2a043b373bc..33c0a6799e9 100644 --- a/noir_stdlib/src/meta/typ.nr +++ b/noir_stdlib/src/meta/typ.nr @@ -14,6 +14,9 @@ impl Type { #[builtin(type_as_slice)] fn as_slice(self) -> Option {} + #[builtin(type_as_struct)] + fn as_struct(self) -> Option<(StructDefinition, [Type])> {} + #[builtin(type_as_tuple)] fn as_tuple(self) -> Option<[Type]> {} diff --git a/test_programs/compile_success_empty/comptime_type/src/main.nr b/test_programs/compile_success_empty/comptime_type/src/main.nr index b2b724db6fd..e3a924ee41e 100644 --- a/test_programs/compile_success_empty/comptime_type/src/main.nr +++ b/test_programs/compile_success_empty/comptime_type/src/main.nr @@ -1,5 +1,9 @@ use std::meta::type_of; +struct Foo { + x: T +} + fn main() { comptime { @@ -66,5 +70,17 @@ fn main() { let yes = true; let bool_type = type_of(yes); assert(bool_type.is_bool()); + + // Check Type::as_struct + assert(u8_type.as_struct().is_none()); + + let foo = Foo { x: 0 }; + let foo_type = type_of(foo); + let (struct_definition, generics) = foo_type.as_struct().unwrap(); + let fields = struct_definition.fields(); + assert_eq(fields.len(), 1); + + assert_eq(generics.len(), 1); + assert_eq(generics[0], field_type_1); } }