Understanding Rust Error E0794

Introduction to Rust Error E0794

Rust Error E0794 occurs when a lifetime parameter of a function definition is called late-bound and specified arguments for these parameters are not allowed. This article explains the details of this error, its causes, and how to resolve it.

Late-bound lifetime parameters

A lifetime parameter in Rust is called late-bound if it meets the following two conditions: 1. Appears in an argument type. 2. Does not appear in a generic type constraint.

Error example

Consider the following erroneous code snippet that generates Rust Error E0794:

fn foo<'a>(x: &'a str) -> &'a str { x }
let _ = foo::<'static>;

In this example, the type of a concrete instance of the 'foo' function is universally quantified over late-bound lifetime parameters. The function is designed to work for any lifetime substituted for the late-bound lifetime parameter, but the specified arguments for these parameters are not allowed, thus generating the error.

How to fix Rust Error E0794

To resolve Rust Error E0794, remove the specified lifetime as shown in the following corrected code snippet:

fn foo<'a>(x: &'a str) -> &'a str { x }
let _ = foo;

Early-bound vs. Late-bound lifetime parameters

Lifetime parameters that are not late-bound are called early-bound. It is important to note that late-bound and early-bound lifetime parameters are declared the same way in function definitions, which may result in confusion. When referring to a function pointer type, universal quantification over late-bound lifetime parameters can be made explicit.

Example with early-bound and late-bound parameters

Take a look at the following code example to understand the difference between early-bound and late-bound lifetime parameters:

trait BarTrait<'a> {}

struct Bar<'a> {
    s: &'a str

impl<'a> BarTrait<'a> for Bar<'a> {}

fn bar<'a, 'b, T>(x: &'a str, _t: T) -> &'a str
where T: BarTrait<'b>

let bar_fn: for<'a> fn(&'a str, Bar<'static>) -> &'a str = bar; // OK
let bar_fn2 = bar::<'static, Bar>; // Not allowed
let bar_fn3 = bar::<Bar>; // OK

In the 'bar' function definition, the lifetime parameter 'a is late-bound, while 'b is early-bound. This distinction is shown in the type annotation for 'bar_fn', where 'a is universally quantified and 'b is substituted by a specific lifetime. You are not allowed to explicitly specify early-bound lifetime arguments when late-bound lifetime parameters are present, as demonstrated by 'bar_fn2'.