linear_generic_param: a linear value is passed to a generic parameter that has not opted in

A linear value is passed to a function that is generic in that parameter (fn pass(x) do x end). An ordinary type variable is unrestricted, so the function body could copy or drop the value, and the compiler does not look inside the body to find out.

A program that triggers it

mod Main do
  needs IO.Console
  always_linear type Token = Token(Int)

  fn consume(t : Token) : Int do
    match t do Token(n) -> n end
  end

  fn pass(x) do x end

  fn main(_console : Cap(IO.Console)) do
    let t = pass(Token(1))
    println(int_to_string(consume(t)))
  end
end

The fix

If the generic function uses the parameter exactly once, mark it linear where the function is defined (linear x : a). That opts it in to receiving linear values, and its body is then checked to use x once. Otherwise, consume the value at the call site instead.

mod Main do
  needs IO.Console
  always_linear type Token = Token(Int)

  fn consume(t : Token) : Int do
    match t do Token(n) -> n end
  end

  fn pass(linear x : a) : a do x end

  fn main(_console : Cap(IO.Console)) do
    let t = pass(Token(1))
    println(int_to_string(consume(t)))
  end
end

Why the rule exists

A type variable used to be unrestricted and instantiable with a linear type, so fn dup(x) do (x, x) end turned one linear value into two. Requiring the opt-in keeps generic code usable with ordinary values and makes the functions that may receive linear values say so.

See also: the language reference.