Skip to main content

Why affine types

Affine types are a version of linear types that do allow only single use of an object as linear types but allow discarding value, i.e. not using it.

Jacy supports affine types, not linear, however, linearity logic is controlled with warnings, i.e. the compiler will give a warning if you didn't use the value.

func foo() {
let r = Rc(0);
let r1 = Rc::clone(r);
}

At the code generation stage, we need to create a so-called "destruction scope", where we will drop the values owned by the scope we exit. The RC r and r1 will be dropped when the body of the function foo ends. Rc implements Drop::drop method which accepts self by-move, thus you cannot drop the value twice.

func foo() {
let r = Rc(0);
let r1 = Rc::clone(r);
}
// Drop scope of the function `foo`
{
Drop::drop(r1);
Drop::drop(r);
}

In this code, if we hadn't affine types, we could drop value r1 or value r twice, and some of them couldn't be dropped correctly.

This example is the reason why affine types are cool, it just presents their main advantage -- data flow control. We know where data goes, from where, and that we lose access to it as it is moved.

Of course, there is the borrowing concept that allows us not to copy or move the data, but alias it with a new object.

Affine types solve many problems while making code stricter and safe from occasional user mistakes.