We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Ownership III: Lifetimes, Explicitly step 15 of 22
Make the lint happy: `'_` in return paths
Four one-line functions that return standard-library iterators. The bodies are already written and already correct. Every one of them still fails the gate, and not one of them contains a lifetime you wrote.
pub fn bytes_of(data: &[u8]) -> slice::Iter<u8> // rejected
pub fn letters(s: &str) -> str::Chars // rejected
pub fn fields(s: &str, sep: char) -> str::Split<char> // rejected
pub fn pairs(v: &[i64]) -> slice::Chunks<i64> // rejected
This is the single most confusing failure a beginner meets, because the error is about lifetimes and you never typed one.
Three syntaxes for one thing
A lifetime can appear in a signature in three different ways:
| group | how it looks | examples |
|---|---|---|
| named | you wrote a name |
&'a str, Person<'a> |
| elided | you wrote a placeholder |
&str, &'_ str, Person<'_> |
| hidden | nothing visible at all |
Person, Iter<u8> |
Iter<u8> is the sting. std::slice::Iter is declared Iter<'a, T> — it
has a lifetime parameter, and a path is allowed to omit it entirely. So
-> slice::Iter<u8> really means -> slice::Iter<'_, u8> with the lifetime
invisible. The rustc lint mismatched_lifetime_syntaxes — warn-by-default
since 1.89, and a hard error here because the gate is -D warnings — fires
when one lifetime is referred to using syntaxes from different groups in a
single signature:
warning: hiding a lifetime that's elided elsewhere is confusing
help: use `'_` for type paths
In bytes_of(data: &[u8]) -> slice::Iter<u8>, the input’s lifetime is
elided (&[u8]) and the output’s is hidden (Iter<u8>). Same lifetime,
two groups, confusing. Write slice::Iter<'_, u8> and both are elided, and the
lint goes quiet.
Note carefully what does not fire: fn f(x: &u8) -> &'_ u8 is fine.
&u8 and &'_ u8 are both in the elided group. The lint is about grouping,
not spelling.
'_ does not mean “no lifetime”
It means “there is a lifetime here; infer it.” That is why it is the fix, not
a way to opt out. And note that elided_lifetimes_in_paths — the lint that
would ban hidden lifetimes outright — is still allow-by-default, “because it
has some known issues”. So '_ in paths is not mandatory in general. Only
consistency within a signature is.
Honesty about the other fix
Naming the lifetime also silences the rustc lint, and it passes this gate:
pub fn bytes_of<'a>(data: &'a [u8]) -> slice::Iter<'a, u8> // accepted
Both positions are then in the named group, which is consistent.
clippy::needless_lifetimes does not fire on this shape, and
clippy::elidable_lifetime_names — which would nudge you back to '_ — is
pedantic, not part of the gate. So: '_ is the idiomatic answer and the one
the compiler suggests, but you are not being graded on idiom here, you are being
graded on consistency. Returning impl Iterator<Item = &u8> + '_ instead is
also a legitimate design and would pass — it hides the concrete iterator type
from your callers, which is a different tradeoff worth thinking about.
The one that trips people up
str::Split is declared Split<'a, P> — two parameters, lifetime first.
Split<'_, char>, not Split<char, '_> (a syntax error) and not
Split<'_> (a missing type argument). Get the slot right.
The entry point
Iterators are not JSON-expressible, so run materialises all four:
pub fn run(v: Vec<i64>, s: String, sep: String)
-> (Vec<u8>, Vec<String>, Vec<String>, Vec<Vec<i64>>)
In order: the bytes of s; each char of s as its own String; s split on
the first character of sep; and v in chunks of two. Two details the tests
check — "".split(',') yields one empty field, not zero, and a trailing
odd element makes a chunk of length one.
Loading visualization…
Stuck?
Rust reference solution
Sign in to attempt this problem and reveal the reference solution.