Template types

Template type definitions provide a shorthand syntax to avoid repeating the definition of methods on common generic types. All of the items within a template type definition are copied into each matching concrete type definition. At the moment, template types are considered unstable and ust be activated with the #unstable(template_types) directive.

For example:

#unstable(template_types)

type<T> ::std::option::Option<T> {
    constructor Some(T);
    constructor None;
    fn unwrap(self) -> T;
    fn is_some(&self) -> bool;
}

type ::std::option::Option<i32> {
    #layout(size = 8, align = 8);
    wellknown_traits(Copy, Debug);
    // the constructors and methods are automatically defined
}

You can also define well-known traits and layouts in template types:

type<T> [T] {
    wellknown_traits(?Sized);
}

type<T> ::std::vec::Vec<T> {
    #layout(size = 24, align = 8);
}

type<T> option::Option<&T> {
    #layout(size = 8, align = 8);
    wellknown_traits(Copy);
}

Note that multiple template definitions can apply to the same concrete type, so Option<&i32> would inherit definitions from the Option<T> template and the Option<&T> template.

You can also override the layout given in a template:

type<T> Box<T> {
    #layout(size = 8, align = 8);
    // Most Boxed types are 8 bytes
}

type<T> Box<i32> {} // Inherits the 8 byte layouts

type Box<dyn crate::MyTrait> {
    #layout(size = 16, align = 8);
    // Boxed trait objects are 16 bytes
}

Zngur will still only emit C++ definitions for the concrete types that are defined. Template definitions on their own do not result in any C++ code. This also means that at the moment, any type mentioned in a template definition must be individually defined as well. For example, the following code will fail to compile unless Option<String> is defined to make Result::<String, i64>::ok valid. If the Option<T> template from above is defined, then we must add a definition for String as well to support Option::<String>::unwrap.

type<T, E> ::std::result::Result<T, E> {
    fn ok(self) -> ::std::option::Option<T>;
}

type ::std::result::Result<::std::string::String, i64> {
    #layout(size = 24, align = 8);
}