packages feed

futhark-0.20.3: docs/error-index.rst

.. _error-index:

Compiler Error Index
====================

Elaboration on type errors produced by the compiler.  Many error
messages contain links to the sections below.

Uniqueness errors
-----------------

.. _use-after-consume:

"Using *x*, but this was consumed at *y*."
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A core principle of uniqueness typing (see :ref:`in-place-updates`) is
that after a variable is "consumed", it must not be used again.  For
example, this is invalid, and will result in the error above::

  let y = x with [0] = 0
  in x

Several operations can *consume* a variable: array update expressions,
calling a function with unique-typed parameters, or passing it as the
initial value of a unique-typed loop parameter.  When a variable is
consumed, its *aliases* are also considered consumed.  Aliasing is the
possibility of two variables occupying the same memory at run-time.
For example, this will fail as above, because ``y`` and ``x`` are
aliased::

  let y = x
  let z = y with [0] = 0
  in x

We can always break aliasing by using a ``copy`` expression::

  let y = copy x
  let z = y with [0] = 0
  in x

.. _not-consumable:

"Would consume *x*, which is not consumable"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This error message occurs for programs that try to perform a
consumption (such as an in-place update) on variables that are not
consumable.  For example, it would occur for the following program::

  let f (a: []i32) =
    let a[0] = a[0]+1
    in a

Only arrays with a a *unique array type* can be consumed.  Such a type
is written by prefixing the array type with an asterisk.  The program
could be fixed by writing it like this::

  let f (a: *[]i32) =
    let a[0] = a[0]+1
    in a

Note that this places extra obligations on the caller of the ``f``
function, since it now *consumes* its argument.  See
:ref:`in-place-updates` for the full details.

You can always obtain a unique copy of an array by using
``copy``::

  let f (a: []i32) =
    let a = copy a
    let a[0] = a[0]+1
    in a

But note that in most cases (although not all), this subverts the
purpose of using in-place updates in the first place.

.. _return-aliased:

"Unique-typed return value of *x* is aliased to *y*, which is not consumable"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This can be caused by a function like this::

  let f (xs: []i32) : *[]i32 = xs

We are saying that ``f`` returns a *unique* array - meaning it has no
aliases - but at the same time, it aliases the parameter *xs*, which
is not marked as being unique (see :ref:`in-place-updates`).  This
violates one of the core guarantees provided by uniqueness types,
namely that a unique return value does not alias any value that might
be used in the future.  Imagine if this was permitted, and we had a
program that used ``f``::

  let b = f a
  let b[0] = x
  ...

The update of ``b`` is fine, but if ``b`` was allowed to alias ``a``
(hence occupying the same memory), then we would be modifying ``a`` as
well, which is a violation of referential transparency.

As with most uniqueness errors, it can be fixed by using ``copy xs``
to break the aliasing.  We can also change the type of ``f`` to take a
unique array as input::

  let f (xs: *[]i32) : *[]i32 = xs

This makes ``xs`` "consumable", in the sense used by the error message.

.. _unique-return-aliased:

"A unique-typed component of the return value of *x* is aliased to some other component"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Caused by programs like the following::

  let main (xs: *[]i32) : (*[]i32, *[]i32) = (xs, xs)

While we are allowed to "consume" ``xs``, as it is a unique parameter,
this function is trying to return two unique values that alias each
other.  This violates one of the core guarantees provided by
uniqueness types, namely that a unique return value does not alias any
value that might be used in the future (see :ref:`in-place-updates`) -
and in this case, the two values alias each other.  We can fix this by
inserting copies to break the aliasing::

  let main (xs: *[]i32) : (*[]i32, *[]i32) = (xs, copy xs)

Size errors
-----------

.. _unused-size:

"Size *x* unused in pattern."
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Caused by expressions like this::

  let [n] (y: i32) = x

And functions like this::

  let f [n] (x: i32) = x

Since ``n`` is not the size of anything, it cannot be assigned a value
at runtime.  Hence this program is rejected.

.. _causality-check:

"Causality check"
~~~~~~~~~~~~~~~~~

Causality check errors occur when the program is written in such a way
that a size is needed before it is actually computed.  See
:ref:`causality` for the full rules.  Contrived example::

  let f (b: bool) (xs: []i32) =
    let a = [] : [][]i32
    let b = [filter (>0) xs]
    in a[0] == b[0]

Here the inner size of the array ``a`` must be the same as the inner
size of ``b``, but the inner size of ``b`` depends on a ``filter``
operation that is executed after ``a`` is constructed.

There are various ways to fix causality errors.  In the above case, we
could merely change the order of statements, such that ``b`` is bound
first, meaning that the size is available by the time ``a`` is bound.
In many other cases, we can lift out the "size-producing" expressions
into a separate ``let``-binding preceding the problematic expressions.