Type Aliases
A type alias gives an existing type a second name. It introduces no new type: the alias and its target are the same type, interchangeable everywhere without a conversion.
TypeAlias ::= 'pub'? 'type' Identifier '=' Type ';'
type UserId = uint64;
type Matrix = float32[2][2];
type Bytes = uint8[..];
type MaybeId = UserId?;
An alias is declared at the top level of a file or inside a module block. Like any declaration it is private to its package unless marked pub.
Transparency
Because an alias names the same type as its target, values pass between the two in both directions, and a type test answers to either spelling:
type Count = int32;
func Main() -> int {
let counted: Count = 7;
let plain: int32 = counted; // no conversion
let back: Count = plain; // and none back
let same = counted is int32; // true
return back as int;
}
An alias also carries everything attached to its target. Its associated constants are reachable through it — Count::Max is int32::Max once int32 is imported from Core — and its methods are callable on it.
The reverse holds too: an extend block written for an alias extends the target type itself.
type Celsius = float64;
extend Celsius {
func Fahrenheit(self: &Celsius) -> float64 {
return self * 1.8 + 32.0;
}
}
After this, every float64 has a Fahrenheit method, not only values declared as Celsius.
An alias is not a distinct type
An alias gives a name, never type safety. Two aliases of the same type are the same type as each other, so nothing stops them being mixed:
type Metres = float64;
type Feet = float64;
func Main() -> int {
let height: Metres = 1.8;
let step: Feet = 2.5;
let nonsense = height + step; // accepted: both are float64
return 0;
}
When the compiler should keep two kinds of value apart, wrap the value in a single-field struct; each struct declaration is a type of its own.
struct Metres {
value: float64;
}
struct Feet {
value: float64;
}
What can be aliased
Any type can be aliased: primitives, slices, arrays, tuples, optionals, sums, fallibles, pointers and references, function types, user-defined types and instantiations of generic types.
struct Point {
x: int;
y: int;
}
struct Box<T> {
value: T;
}
type Position = Point;
type IntBox = Box<int>;
type Pair = (int, int);
type Callback = func(int) -> bool;
func Main() -> int {
let here = Position { x: 1, y: 2 };
let boxed: IntBox = Box<int> { value: 3 };
let pair: Pair = (4, 5);
return here.x + boxed.value + pair.1; // 9
}
An alias of a struct can be used to write a struct literal, as Position { x: 1, y: 2 } shows.
rux 0.4.0 resolves an alias where it is declared, so the type it names must be declared above it in the file. It does not yet accept a struct literal written through an alias of a generic instantiation, such as
IntBox { value: 3 }; write Box<int> { value: 3 }. And an alias named through a module path from outside its module, such as Units::Metres, is not yet resolved to its target.An alias cannot take type parameters. type Pair<T> = (T, T); is a syntax error, error: expected '=' after the type alias name before '<'; write a generic struct instead.
An alias cannot name itself, directly or through other aliases:
type A = B;
type B = A;
error: type alias 'A' has a cyclic definition
Built-in aliases
Four primitive names are aliases, declared in the Core package with pub type:
| Alias | Target | Meaning |
|---|---|---|
bool | bool8 | The everyday boolean |
byte | uint8 | A raw byte of storage, as opposed to a small number |
char | char32 | One Unicode scalar value |
float | float64 | The everyday floating-point type |
They behave exactly like their targets — same representation, ABI, constants, conversions and overloads — and compiler messages name the target: a mistake with a bool reports bool8. The names can be used as types without an import; their associated constants, like any primitive's, need one, such as import Core::byte; for byte::Max.
int and uint are not aliases. They are distinct primitive types that convert implicitly to and from int64 and uint64; see Integers.
See also
- Types — type identity and conversions
- Function types — naming a callable signature
- Structs — when a distinct type is wanted
- Type alias — the lesson