rust-lang / rust-lang/rust

Better help message for missing lifetime specifier

Open
#143,389 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

A-diagnostics T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Code

This is a simple sieve that currently compiles fine:

const MAX: usize = 1_000_000;

fn create_sieve<'a, const LENP: usize>(sieve: &mut [bool; MAX],
                                       primes: &'a mut [u32; LENP]) -> &'a [u32] {
    const SM: usize = MAX.isqrt();
    sieve[0] = false;
    sieve[1] = false;

    let mut primes_len = 0;

    let mut i = 0;
    while i < SM {
        while i < SM && !sieve[i] {
            i += 1;
        }

        primes[primes_len] = i as u32;
        primes_len += 1;

        let mut j = 2 * i;
        while j < MAX {
            sieve[j] = false;
            j += i;
        }
        i += 1;
    }

    for j in i .. MAX {
        if sieve[j] && primes_len < LENP {
            primes[primes_len] = j as u32;
            primes_len += 1;
        }
    }

    &primes[.. primes_len]
}

fn main() {}

If I don't put the 'a lifetime there (you can think of this as a precedent version):

const MAX: usize = 1_000_000;

fn create_sieve<const LENP: usize>(sieve: &mut [bool; MAX],
                                   primes: &mut [u32; LENP]) -> &[u32] {
    const SM: usize = MAX.isqrt();
    sieve[0] = false;
    sieve[1] = false;

    let mut primes_len = 0;

    let mut i = 0;
    while i < SM {
        while i < SM && !sieve[i] {
            i += 1;
        }

        primes[primes_len] = i as u32;
        primes_len += 1;

        let mut j = 2 * i;
        while j < MAX {
            sieve[j] = false;
            j += i;
        }
        i += 1;
    }

    for j in i .. MAX {
        if sieve[j] && primes_len < LENP {
            primes[primes_len] = j as u32;
            primes_len += 1;
        }
    }

    &primes[.. primes_len]
}

fn main() {}
Current output

Currently (rustc 1.90.0-nightly 667787527 2025-07-02) rust gives an error, because it refuses to guess where the output comes from:

error[E0106]: missing lifetime specifier
 --> ...\test2.rs:4:65
  |
3 | fn create_sieve<const LENP: usize>(sieve: &mut [bool; MAX],
  |                                           ----------------
4 |                                    primes: &mut [u32; LENP]) -> &[u32] {
  |                                            ----------------     ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `sieve` or `primes`
help: consider introducing a named lifetime parameter
  |
3 ~ fn create_sieve<'a, const LENP: usize>(sieve: &'a mut [bool; MAX],
4 ~                                    primes: &'a mut [u32; LENP]) -> &'a [u32] {
  |
Desired output

I suggest to replace the current suggestion and replace (for simple cases) with a better guess generated from just the signature, so it doesn't use the lifetime of an array of bools if the output is a slice of u32:

fn create_sieve<'a, const LENP: usize>(sieve: &mut [bool; MAX],
                                       primes: &'a mut [u32; LENP]) -> &'a [u32] {

In more complex cases it's perhaps better to avoid guessing, and avoid giving a suggestion.

Rationale and extra context

Many cases are simple, in such cases guessing could be reasonable.

Other cases
Rust Version
rustc 1.90.0-nightly (667787527 2025-07-02)
binary: rustc
commit-hash: 6677875279b560442a07a08d5119b4cd6b3c5593
commit-date: 2025-07-02
host: x86_64-pc-windows-gnu
release: 1.90.0-nightly
LLVM version: 20.1.7
Anything else?

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing rustc's E0106 missing-lifetime diagnostic and its suggestion generation for function signatures. Done means simple cases suggest the lifetime on the input matching the returned slice, while complex cases avoid guessing and omit the suggestion, with coverage for both outcomes.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.