Skip to main content
Version: dev

Type Coercions

When one type is required in Noir code but a different type is given, the compiler will typically issue a type error. There are a few cases however where the compiler will instead automatically perform a type coercion. These are typically limited to a few type pairs where converting from one to the other will not sacrifice performance or correctness. Currently, Noir will will try to perform the following type coercions:

Actual TypeExpected Type
[T; N][T]
fn(..) -> Runconstrained fn(..) -> R
str<N>CtString
fmtstr<N, T>CtString
&mut T&T

Note that:

  • Conversions are only from the actual type to the expected type, never the other way around.
  • Conversions are only performed on the outermost type, they're never performed within a nested type.
  • CtString is a compile-time only type, so this conversion is only valid in comptime code.
  • &T requires the experimental -Zownership flag to be enabled.

Examples:

fn requires_slice(_slice: [Field]) {}
comptime fn requires_ct_string(_s: CtString) {}

fn main() {
let array: [Field; 4] = [1, 2, 3, 4];

// Ok - array is converted to a slice
requires_slice(array);
// equivalent to:
requires_slice(array.as_slice());

// coerce a constrained function to an unconstrained one:
let f: unconstrained fn([Field]) = requires_slice;

comptime {
// Passing a str<6> where a CtString is expected
requires_ct_string("hello!")
}
}