Skip to main content

Type System

Builtin Types

Rue has a structural type system, which is similar to duck typing. One key difference is that types with different semantics must be cast, even if they have the same structure.

Any

Makes no assumption about the structure of the value. Anything can be assigned to Any.

let value: Any = (14, 32);

List

Represents a recursive structure of nested pairs.

let value: List<Int> = [1, 2, 3];

Bytes

Any atomic CLVM value can be represented as Bytes. However, only strings and hex literals are treated as Bytes by default.

let hex: Bytes = 0xFACE;
let string: Bytes = "Hello";

When you add byte values together, they will be concatenated.

Bytes32

When an atomic value is exactly 32 bytes in length, it can be represented as Bytes32. This enhances type safety of things such as sha256 hashes.

let hash: Bytes32 = 0x38b1cec180a0bc0f5ec91097cec51971df126e3b18af54ddba4a3e4a36f9c285;

PublicKey

When an atomic value is exactly 48 bytes in length, it can be represented as PublicKey.

More specifically, PublicKey is a BLS12-381 G1Element.

let pk: PublicKey = 0xb3596acaa39f19956f77b84cef87a684ea0fec711e6ec9e55df3cffd4a6e05d3e2da842433dccb6042ee35c14d892206;

When you add public keys together, it will call the CLVM g1_add operator (formerly known as point_add).

Int

Any atomic CLVM value can be represents as Int.

let num: Int = 42;

You can perform standard arithmetic on integers, as well as bitwise math:

let a: Int = ((42 * 34) / 8 + 9 - -10) % 16;
let b: Int = ((100 >> 3) << 2) & 420 | ~6;

Bool

A boolean is either true or false.

let flag: Bool = true;

You can use logical operators on booleans:

let value: Bool = (true && false) || true;

nil

The simplest type of them all, nil only has one value:

let value: nil = nil;

Inference

In many cases, the type of variables can be inferred based on their value.

For example:

let value = 42;

Here, value is known to be Int even though it wasn't specified. It's generally cleaner to omit the type in places where it's obvious.

Casting

Structural Cast

You can cast the type of a value with the as keyword. This can only be done as long as both types are structurally related.

For example, casting an Int to Bytes is fine since both of them are atomic values:

let value = 42;
let bytes = 42 as Bytes;

You can cast more complicated types such as pairs:

let pair = ("Hello, ", "world!");
let casted = pair as (Int, Int);

However, this is not allowed, since the structure would differ (and this could cause runtime errors):

let pair = (42, 34);
let num = pair as Int; // Type error

Reinterpret Cast

Sometimes, you need to change the type of a variable without the type system getting in the way.

warning

This is unsafe and could result in hard to debug issues at runtime if you are not careful. It should be scrutinized when auditing Rue code.

There is a built in function called cast which will do this:

let pair = (42, 34);
let num = cast::<Int>(pair); // Ok