Type
std::meta::typ
contains methods on the built-in Type
type used for representing
a type in the source program.
Functions
pub comptime fn fresh_type_variable() -> Type {}
Creates and returns an unbound type variable. This is a special kind of type internal
to type checking which will type check with any other type. When it is type checked
against another type it will also be set to that type. For example, if a
is a type
variable and we have the type equality (a, i32) = (u8, i32)
, the compiler will set
a
equal to u8
.
Unbound type variables will often be rendered as _
while printing them. Bound type
variables will appear as the type they are bound to.
This can be used in conjunction with functions which internally perform type checks
such as Type::implements
or Type::get_trait_impl
to potentially grab some of the types used.
Note that calling Type::implements
or Type::get_trait_impl
on a type variable will always
fail.
Example:
trait Serialize<let N: u32> {}
impl Serialize<1> for Field {}
impl<T, let N: u32, let M: u32> Serialize<N * M> for [T; N]
where
T: Serialize<M>,
{}
impl<T, U, let N: u32, let M: u32> Serialize<N + M> for (T, U)
where
T: Serialize<N>,
U: Serialize<M>,
{}
Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L14-L29
let typevar1 = std::meta::typ::fresh_type_variable();
let constraint = quote { Serialize<$typevar1> }.as_trait_constraint();
let field_type = quote { Field }.as_type();
// Search for a trait impl (binding typevar1 to 1 when the impl is found):
assert(field_type.implements(constraint));
// typevar1 should be bound to the "1" generic now:
assert_eq(typevar1.as_constant().unwrap(), 1);
// If we want to do the same with a different type, we need to
// create a new type variable now that `typevar1` is bound
let typevar2 = std::meta::typ::fresh_type_variable();
let constraint = quote { Serialize<$typevar2> }.as_trait_constraint();
let array_type = quote { [(Field, Field); 5] }.as_type();
assert(array_type.implements(constraint));
// Now typevar2 should be bound to the serialized pair size 2 times the array length 5
assert_eq(typevar2.as_constant().unwrap(), 10);
Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L129-L149
Methods
as_array
pub comptime fn as_array(self) -> Option<(Type, Type)> {}
If this type is an array, return a pair of (element type, size type).
Example:
comptime {
let array_type = quote { [Field; 3] }.as_type();
let (field_type, three_type) = array_type.as_array().unwrap();
assert(field_type.is_field());
assert_eq(three_type.as_constant().unwrap(), 3);
}
as_constant
pub comptime fn as_constant(self) -> Option<u32> {}
If this type is a constant integer (such as the 3
in the array type [Field; 3]
),
return the numeric constant.
as_integer
pub comptime fn as_integer(self) -> Option<(bool, u8)> {}
If this is an integer type, return a boolean which is true
if the type is signed, as well as the number of bits of this integer type.
as_mutable_reference
comptime fn as_mutable_reference(self) -> Option<Type> {}
If this is a mutable reference type &mut T
, returns the mutable type T
.
as_slice
pub comptime fn as_slice(self) -> Option<Type> {}
If this is a slice type, return the element type of the slice.
as_str
pub comptime fn as_str(self) -> Option<Type> {}
If this is a str<N>
type, returns the length N
as a type.
as_struct
pub comptime fn as_struct(self) -> Option<(StructDefinition, [Type])> {}
If this is a struct type, returns the struct in addition to any generic arguments on this type.
as_tuple
pub comptime fn as_tuple(self) -> Option<[Type]> {}
If this is a tuple type, returns each element type of the tuple.
get_trait_impl
pub comptime fn get_trait_impl(self, constraint: TraitConstraint) -> Option<TraitImpl> {}
Retrieves the trait implementation that implements the given
trait constraint for this type. If the trait constraint is not
found, None
is returned. Note that since the concrete trait implementation
for a trait constraint specified in a where
clause is unknown,
this function will return None
in these cases. If you only want to know
whether a type implements a trait, use implements
instead.
Example:
comptime {
let field_type = quote { Field }.as_type();
let default = quote { Default }.as_trait_constraint();
let the_impl: TraitImpl = field_type.get_trait_impl(default).unwrap();
assert(the_impl.methods().len(), 1);
}
implements
pub comptime fn implements(self, constraint: TraitConstraint) -> bool {}
true
if this type implements the given trait. Note that unlike
get_trait_impl
this will also return true for any where
constraints
in scope.
Example:
fn foo<T>() where T: Default {
comptime {
let field_type = quote { Field }.as_type();
let default = quote { Default }.as_trait_constraint();
assert(field_type.implements(default));
let t = quote { T }.as_type();
assert(t.implements(default));
}
}
is_bool
pub comptime fn is_bool(self) -> bool {}
true
if this type is bool
.
is_field
pub comptime fn is_field(self) -> bool {}
true
if this type is Field
.
is_unit
comptime fn is_unit(self) -> bool {}
true
if this type is the unit ()
type.
Trait Implementations
impl Eq for Type
impl Hash for Type
Note that this is syntactic equality, this is not the same as whether two types will type check
to be the same type. Unless type inference or generics are being used however, users should not
typically have to worry about this distinction unless std::meta::typ::fresh_type_variable
is used.