Mehdi Akiki
Rust Failure Atlas / Runtime, memory, and library APIs

RFA-525 · Case file with fixtures · Case 497 of 694 · Compiler evidence

Static Is a Built-In Rust Lifetime, Not a Parameter Name

The built-in 'static lifetime means validity for the program duration. Generic lifetime names represent caller-chosen relationships, so use another name when the function should accept ordinary borrows.

Reviewed
Rust
Rust 1.98.1, edition 2024
Targets
all Rust targets
Profiles
dev, release, test

Direct answer

What this Rust failure means

Why it happens
Static already denotes program-duration validity, while a generic lifetime parameter is a caller-selected relationship that needs another declared name.
First discriminating check
Identify the real owner and use a generic lifetime for ordinary borrows, reserving static references or bounds for genuine program-long or ownership-free requirements.

I wrote fn borrow<'static>(...) as if 'static were a new generic name. Rust emitted E0262 because 'static is a special built-in lifetime and cannot be redeclared.

The failing fixture also risks a deeper misunderstanding: a generic lifetime and the actual static lifetime promise very different APIs.

Static already has language-defined meaning

'static denotes a lifetime that lasts for the remaining duration of the program. String literals often have this lifetime, and owned values can satisfy certain 'static bounds when they contain no shorter borrowed references.

The name is not an empty slot awaiting definition. The official E0262 page rejects it as a parameter name for this reason.

I reserve it for the built-in meaning.

The repaired fixture uses a caller-chosen lifetime

The repaired fixture declares 'a, accepts &'a str, and returns &'a str. The caller may choose a short borrow from a local String.

This is more general than requiring &'static str. The function promises only that the output remains tied to the input borrow.

The runtime check proves ordinary owned local text can participate.

A static bound does not always mean a static reference

T: 'static means T contains no borrowed data that expires sooner than the program. An owned String can satisfy it even though the particular String value will be dropped.

&'static str specifically is a reference valid for the program duration. Confusing these two forms leads to unnecessary leaks or rejected owned values.

I read whether 'static bounds a type or labels a reference.

Generic names describe relationships

Names such as 'a, 'input, and 'request do not determine duration by themselves. They let a declaration relate inputs, outputs, and stored fields.

Descriptive names help when several lifetimes interact, while 'a is fine for one simple relation. Renaming a generic lifetime does not change behaviour if all uses and bounds remain equivalent.

The Reference on lifetime bounds explains outlives relationships.

Static is often an overly strong repair

When the compiler asks for a lifetime, adding 'static may silence one error by forbidding short borrows. Some developers then leak memory to manufacture static references.

I first identify the real owner. Request parsing, views, and temporary adapters usually need a generic relation. Global tables and embedded literals may honestly use static references.

The longest lifetime is not automatically the best lifetime.

Async tasks expose the distinction

Spawned tasks often require captured values to be 'static because the task may outlive the creating stack frame. Moving owned data can satisfy this without keeping it forever.

Borrowing a local reference usually cannot. I clone or move the owner when appropriate, use scoped concurrency when supported, or restructure task ownership. Renaming a lifetime parameter to 'static cannot change the captured value's validity.

Static data and leaked data have different intent

String literals and true global constants are naturally static because their storage belongs to the program image or global runtime. Box::leak can turn owned heap storage into a long-lived reference by intentionally giving up automatic reclamation. Both may type-check as 'static, but their operational cost and ownership story differ.

I reserve leaking for bounded, process-lifetime registries where permanent allocation is a deliberate design. Using it repeatedly for requests or messages creates unbounded growth. A lifetime error should send me back to ownership first, not immediately toward leakage.

APIs should avoid demanding static unnecessarily

A callback stored only for one scope can accept a scoped borrow. Requiring 'static merely because an early implementation used a global executor narrows reuse. I place the bound at the component that truly stores or spawns work beyond the current scope, keeping inner algorithms generic over shorter lifetimes.

My E0262 checklist

  • Did I try to declare the reserved name 'static?
  • Should this be a caller-chosen generic lifetime instead?
  • Is 'static applied to a reference or as a type bound?
  • What owner actually keeps the data alive?
  • Would a shorter borrow make the API more useful?
  • Am I considering a memory leak only to satisfy a bound?
  • Does a spawned task need owned data rather than a static reference?
  • Does the repaired test use non-static local data?

The core principle is that 'static already names one special program-wide validity condition. Generic lifetimes use other names to describe the real caller-selected relationships among borrows.